1. PREPARE

Although social network analysis (SNA) and its educational antecedents date back to the early 1900s, public and scholarly interest in social network analysis did not really take off until the turn of the century(Carolan 2014). Applications of social network analysis has experienced exponential growth, and across a wide range of phenomena, as documented by a number of studies.

Despite educational research lagging behind other fields, an increase in the use of digital learning resources and data collected by these educational technologies, as well as improved access to training and tools for collecting and analyzing these data, has greatly facilitated the application of network analysis to teaching and learning.

SNA Module 1: The Social Network Perspective and MOOC-Eds is designed to prepare LASER Institute scholars for collecting, processing, and analyzing relational data from a real-world study. Specifically, the three Learning Labs that make up this module address the following topics:

1a. Review the Research

In Social Network Analysis and Education: Theory, Methods & Applications, Carolan (2014) notes that:

the social network perspective is one concerned with the structure of relations and the implication this structure has on individual or group behavior and attitudes

More specifically, Carolyn cites the following four features used by Freeman (2004) to define the social network perspective:

  1. Social network analysis is motivated by a relational intuition based on ties connecting social actors.

  2. It is firmly grounded in systematic empirical data.

  3. It makes use of graphic imagery to represent actors and their relations with one another.

  4. It relies on mathematical and/or computational models to succinctly represent the complexity of social life.

For Unit 1, our walkthrough will be guided by previous research and evaluation work conducted by the Friday Institute for Educational Innovation as part of the Massively Open Online Courses for Educators (MOOC-Ed) initiative. The study introduced next and the hands-on analysis with R in this walkthrough will help to illustrate these four defining features of the social network perspective.

A Social Network Perspective in MOOC-Eds

Kellogg, S., Booth, S., & Oliver, K. (2014). A social network perspective on peer supported learning in MOOCs for educatorsInternational Review of Research in Open and Distributed Learning15(5), 263-289.

Research Context

In the spring of 2013, The Friday Institute launched the MOOC-Ed Initiative to explore the potential of delivering personalized, high-quality professional development to educators at scale (Kleiman et al., 2013). In collaboration with the Alliance for Excellent Education, the Friday Institute launched this initiative with a 6-week pilot course called Planning for the Digital Learning Transition in K-12 Schools (DLT 1), which was offered again in September 2013 (DLT 2). This course was designed to help school and district leaders plan and implement K-12 digital learning initiatives.

Academics, as well as pundits from traditional and new media, have raised a number of concerns about MOOCs, including the lack of instructional and social supports. Among the core design principles of MOOC-Eds are collaboration and peer-supported learning. It is an assumption of this study that challenges arising form this problem of scale can be addressed by leveraging these massive numbers to develop robust online learning communities.

This mixed-methods case study used both SNA and qualitative methods to better understand peer support in MOOC-Eds through an examination of the characteristics, mechanisms, and outcomes of peer networks. Findings from this study demonstrate that even with technology as basic as a discussion forum, MOOCs can be leveraged to foster these networks and facilitate peer-supported learning. Although this study was limited to two unique cases along the wide spectrum of MOOCs, the methods applied provide other researchers with an approach for better understanding the dynamic process of peer supported learning in MOOCs.

Data Sources

MOOC-Ed registration form. All participants completed a registration form for each MOOC-Ed course. The registration form consists of self-reported demographic data, including information related to their professional role and work setting, years of experience in education, and personal learning goals.

MOOC-Ed discussion forums. All peer interaction, including peer discussion, feedback, and reactions (e.g., likes), take place within the forum area of MOOC-Eds, which are powered by Vanilla Forums. Because of the specific focus on peer supported learning, postings to or from course facilitators and staff were removed from the data set. Finally, analyses described below exclude more passive forms of interactions (i.e., read and reaction logs), and include only postings among peers.

For our Unit 1 walkthrough, we’ll take a look at data from the original Digital Learning Transition in K-12 Schools (DLT 1) that was not included in this study to allow for comparisons to the findings in this study. For your independent analysis next week, you may want to consider working with the DLT 2 data to see if you can replicate some of the findings from this paper!

Note: In the data we’re using, instructors have not yet been removed and only direct replies to forum posts have been included, though “weaker” ties like reactions with emoticons and even views of posts were captured in this study.

👉 Your Turn

Take a quick look at the Description of the Dataset section from the Massively Open Online Course for Educators (MOOC-Ed) network dataset BJET article and the accompanying data sets stored on Harvard Dataverse that we’ll be using for this walkthrough.

In the space below, type a brief response to the following questions:

  1. What were some of the steps necessary to construct this dataset?

  2. What two “node attributes” from the dataset that might be useful for predicting participants who may be more engaged or central to the network? Why did you select those two?

  3. What else do you notice/wonder about this dataset?

1b. Identify a Question(s)

A Social Network Perspective on Peer Supported Learning in MOOC-Eds was framed by three primary research questions related to peer supported learning:

  1. What are the patterns of peer interaction and the structure of peer networks that emerge over the course of a MOOC-Ed?

  2. To what extent do participant and network attributes (e.g., homophily, reciprocity, transitivity) account for the structure of these networks?

  3. To what extent do these networks result in the co-construction of new knowledge?

For our very first walkthrough, we are going to focus exclusively on RQ1 from the original study and our question of interest about our discussion network is:

To what extent, did educators engage with other participants in the discussion forums?

👉 Your Turn

Based on what you know about networks and the context so far, what other research questions might ask we ask in this context that a social network perspective might be able to answer?

In the space below, type a brief response to the following questions:

-

We’ll revisit your response towards the end and provide an opportunity to refine your research question after you know the data a little better.

1c. Load Libraries

As highlighted in Chapter 6 of Data Science in Education Using R (DSIEUR):

Packages are shareable collections of R code that can contain functions, data, and/or documentation. Packages increase the functionality of R by providing access to additional functions to suit a variety of needs.

You can always check to see which packages have already been installed and loaded into RStudio Cloud by looking at the the Files, Plots, & Packages Pane in the lower right hand corner of RStudio as shown in the following screenshot:

You should see installed some familiar tidytext packages from our Getting Started Walkthrough like {dplyr} and {readr} which we’ll be using again shortly. You should also see an important package call {igraph} that we will rely on heavily for our network analyses in this course.

If you are working in RStudio Desktop, or notice that the packages have not been installed and/or loaded, run the following install.packages() function code to install the {tidyverse} and {igraph} packages:

install.packages("tidyverse")
install.packages("igraph") 

Let’s go ahead and use the library() function for the {tidyverse} package and review which packages from the tidyverse collection of packages that this package also loads.

Click the green arrow to run the following code and load our packages:

library(tidyverse)

🎉 igraph Package 📦

For our Unit 1 Walkthrough, we will rely heavily on the igraph network analysis package. The main goals of the igraph package and the collection of network analysis tools it contains are to provide a set of data types and functions for:

  1. pain-free implementation of graph algorithms,

  2. fast handling of large graphs, with millions of vertices (i.e., actors or nodes) and edges,

  3. allowing rapid prototyping via high level languages like R.

Run the code chunk below to load the {igraph} library:

library(igraph)

👉 Your Turn

Take a look at the messages from the output after loading the igraph library. What tidyverse packages share identically named functions with igraph?

Write your response in the space below.

-

🧶 Knit & Check ✅

Congrats! You’re ready to start wrangling some data! Before proceeding further, knit your document and check to see if you encounter any errors.


2. WRANGLE

In general, data wrangling involves some combination of cleaning, reshaping, transforming, and merging data (Wickham & Grolemund, 2017). The importance of data wrangling is difficult to overstate, as it involves the initial steps of going from the raw data to a dataset that can be explored and modeled (Krumm et al, 2018).

For our data wrangling this week, we’re keeping it simple since working with network data is a bit of a departure from our working with rectangular data frames. Our primary goals for Unit 1 are learning how to:

  1. Import Data. An obvious and also important first step, we need to “read” our data into R and learn about formatting for edge-lists and node attribute files.

  2. Create a Network Object. Before performing network analyses, we’ll need to convert our data frames into special data format for working with relational data.

  3. Simplify Network. Finally, we’ll learn about a handy simplify() function in the {igraph} package for collapsing multiple ties between actors and removing “self-loops.”

2a. Import Data

The Edge-List Format

To get started, we need to import, or “read,” our data into R. The function used to import your data will depend on the file format of the data you are trying to import, but R is pretty adept at working with many files types.

Take a look in the /data folder in your Files pane. You should see the following .csv files:

  • dlt1-edgelist.csv

  • dlt1-nodes.csv

As its name implies, the first file dlt1-edgelist.csv is an edge-list that contains information about each tie, or relation between two actors in a network. In this context, a “tie” is a reply by one participant in the discussion forum to the post of another participant – or in some cases to their own post! These ties between a single actor are called “self-loops” and as we’ll see later in this section, igraph has a special function to remove these self loops from a sociogram, or network visualization.

The edge-list format is slightly different than other formats you have likely worked with before in that the values in the first two columns each row represent a dyad, or tie between two nodes in a network. An edge-list can also contain other information regarding the strength, duration, or frequency of the relationship, sometime called “weight,” in addition to other “edge attributes.”

In addition to our Sender and Reciever dyad pairs, our DLT 1 dataset contains the following edge attributes:

  • Sender = Unique identifier of author of comment

  • Receiver = Unique identifier of identified recipient of comment

  • Timestamp = Time post or reply was posted

  • Parent = Primary category or topic of thread

  • Category = Subcategory or subtopic of thread

  • Thread_id = Unique identifier of a thread

  • Comment_id = Unique identifier of a comment\

Let’s use the read_csv() function from the {readr} package introduced in the Getting Started walkthrough to read in our edge-list and print the new ties data frame:

ties <- read_csv("data/dlt1-edgelist.csv", 
                 col_types = cols(Sender = col_character(), 
                                  Receiver = col_character(), 
                                  `Category Text` = col_skip(), 
                                  `Comment ID` = col_character(), 
                                  `Discussion ID` = col_character()))

ties

Note the addition of the col_types = argument for changing the column types to character strings since the numbers for those particular columns indicate actors (Sender and Reciever) and attributes (Comment_ID and Discussion_Id). We also skipped the Category Text since this was left blank for deidentification purposes.

RStudio Tip: Importing data and dealing with data types can be a bit tricky, especially for beginners. Fortunately, RStudio has an “Import Dataset” feature in the Environment Pane that can help you use the {readr} package and associated functions to greatly facilitate this process.

👉 Your Turn

Consider the example pictured below of a discussion thread from the Planning for the Digital Learning Transition in K-12 Schools (DLT 1) where our data orginated. This thread was initiated by participant I, so the comments by J and N are considered to be directed at I. The comment of B, however, is a direct response to the comment by N as signaled by the use of the quote-feature as well as the explicit mentioning of N’s name within B’s comment.

Now answer the following questions as they relate to the DLT 1 edge-list we just read into R.

  1. Which actors in this thread are the Sender and the Reciever? Which actor is both?

  2. How many dyads are in this thread? Which pairs of actors are dyads?

Sidebar: Unfortunately, these types of nuances in discussion forum data as illustrated by this simple example are rarely captured through automated approaches to constructing networks. Fortunately, the dataset you are working with was carefully reviewed to try and capture more accurately the intended recipients of each reply.

Node Attributes

The second file we’ll be using contains all the nodes or actors (i.e., participants who posted to the discussion forum) as well as some of their attributes such as gender and years of experience in education.

Carolyn (2013) notes that most social network analyses include variables that describe attributes of actors, ones that are either categorical (e.g., sex, race, etc.) or continuous in nature (e.g., test scores, number of times absent, etc.). These attributes that can be incorporated into a network graph or model, making it more informative and can aid in testing or generating hypotheses.

These attribute variables are typically included in a rectangular array, or dataframe, that mimics the actor-by-attribute that is the dominant convention in social science, i.e. rows represent cases, columns represent variables, and cells consist of values on those variables.

As an aside, Carolyn also refers to this historical preference by researchers for “actor-by-attribute” data, in the absence of relational data in which the actor has been removed their social context, as the “sociological meatgrinder” in action. Specifically, this historical approach assumes that the actor does not interact with anyone else in the study and that outcomes are solely dependent of the characteristics of the individual.

Regardless, let’s read in our node attribute file and take a look at the actors and their attributes included in our dataset:

actors <- read_csv("data/dlt1-nodes.csv", 
                   col_types = cols(UID = col_character(), 
                                    Facilitator = col_character(), 
                                    expert = col_character(), 
                                    connect = col_character()))

👉 Your Turn

Use the code chunk below and a function of your choosing to take a look at the actors data frame:

Match up the attributes included in the node file with the following codebook descriptors. The first one has been done as an example.

  • Facilitator = Identification of course facilitator (1 = instructor)
  • Dummy variable for whether participants listed networking/collaboration with others as one of their course goals on the registration form
  • Identifier of “expert panelists” invited to course to share experience through recorded Q&A
  • Identification of course facilitator (1 = instructor)
  • Professional role (eg, teacher, librarian, administrator)
  • Years of experience as an educator
  • Works with elementary, middle, and/or high school students
  • Initial assignment of discussion group

2b. Create Network Object

Before we can begin using many of the functions from the {igraph} package for summarizing and visualizing our DLT 1 network, we first need to convert the data frames that we imported into an igraph network object, or an igraph graph. 🤷‍♂

Convert to igraph Graph

To do that, we will use the graph_from_data_frame() function. Note that I included the eval=FALSE argument in the code block below to prevent this code from running when we knit our final document. Otherwise it will produce an error since we can’t include help documentation in our knitted HTML file.

Run the following code to take a look at the help documentation for this function:

?graph_from_data_frame

You probably saw that this particular function takes the following three arguments, two of which are data frames:

  • d describes the edges of the network. The first two columns are the IDs of the source and the target node for each edge, in our case the Sender and Reviever of a discussion post – the order matters! The following columns are edge attributes such as weight, type, label, or anything else.

  • vertices starts with a column of node IDs and any following columns are interpreted as node attributes.

  • directed determines whether or not to create a directed graph.

Run the following code to specify our ties data frame as the edges of our network, our actors data frame for the vertices of our network and their attributes, and indicate that this is indeed a directed network.

network <- graph_from_data_frame(d = ties, 
                                 vertices = actors, 
                                 directed = T) 

network

Carolyn (2013) reminds us that one of the simplest and often ignored structural property of a social network is its size and explains that:

size is simply a measure of the number of nodes in the network.

He notes that the size of a network plays an important role in determining what happens in the network. For example, in a classroom of 30 students, it is not hard to imagine that the pattern of who communicates with whom will look much different than if the network consisted of hundreds or even thousands of students like in a MOOC.

👉 Your Turn

Take a look at the very first line of the output which contains some basic information about our network and answer the following questions:

  1. How many nodes and edges are in our network? Is this consistent with the number of observations in our data frames? Hint: Check the Environment pane.

  2. The “D” and the “N” indicate that this is a Directed network and has the Name vertex attributes set. Why do the two spaces that follow these letters have dashes? Hint: check the help files.

  3. Which vertex attribute did igraph interpret as numeric?

Simplify Graph

As you saw from the network output, our dataset has 2529 edges or ties and just a quick scan of the edges in the network shows that edges like 356 -> 444 occur at least more than once. So we know that participant 356 has replied to participant 444 at least twice.

Fortunately, the {igraph} package has a simplify() function for collapsing multiple edges so they are not represented more than once when we want visually depict our network with a sociogram.

Let’s use that function to simplify our network and save it as a simple_network, or a simple graph, which contains no self-loops or duplicate edges and which by default the simplify() function removes:

simple_network <- simplify(network, remove.loops = TRUE) 

simple_network

Note that simplify() removes self-loops by default, this does not really need to be included. If you wanted to keep them, you would simply set this to FALSE.

👉 Your Turn

Take a look at the output for our simple graph now and answer the following questions:

  1. How many unique edges are in the network? Why do you think this is considerably less than our total edges?

  2. Did we potentially lose any important or useful information by collapsing multiple edges into a single edge or by removing self-loops?

Add Edge Weights

We noted earlier that edges can also contain attributes such as strength, duration or frequency, sometime called “weight.” These weights can not only help us better understand the relationship between two actors, but also aid in visualization and modeling later on.

When we used the simplify() function earlier, it collapsed our duplicate edges but we lost some vital information as a result, namely the frequency of replies among pairs of educators in our discussion forum.

Fortunately, the simplify() function contains an argument that will allow us to count the number of ties between two actors, similar to how we might use the count() function in the {dplyr} package like so:

edge_weights <- count(ties, Sender, Receiver)

edge_weights

In this case, we see that participant 1 replied to participant 144 twice throughout the course.

To add weights to our simplified network, we first need to add a weight variable to the edges in our original network igraph object.

The {igraph} package has a unique syntax for working with attributes of network objects. To add a weight attribute to the E() edges in our network we’ll use the $ operator which can be used to create a new weight variable – or select a variable as we’ll see later on – and we’ll use the <- assignment operator to add an initial value of 1 for the weight of each edge.

Let’s put that all together and run the code to add a weight of 1 to each edge in our network

E(network)$weight <- 1  

Now let’s take a look at our igraph network object again:

network

We can see that our network is now weighted as indicated by the “W” and that our new weight attribute has been added.

We can now use the edge.attr.comb = argument to “sum” the weights for each occurrence of a pair of actors, so if 1 replied to participant 144 five times over the course of the MOOC-Ed, there would be a weight of 5 for that pair.

Run the code to simplify our weighted network:

weighted_network <- simplify(network,
                             edge.attr.comb = list(weight="sum")
                             )

Let’s take a look at the output and ignore the error message for now:

weighted_network

👉 Your Turn

Take a look at the output for our simple graph now and answer the following questions:

  1. How does the number of total edges and unique edges this compare to the totals reported for the DLT 2 course in our guiding study?

🧶 Knit & Check ✅

Congrats! You made it to the end of data wrangling section and are ready to start analysis! Before proceeding further, knit your document and check to see if you encounter any errors.


3. EXPLORE

As noted in the Getting Started Walkthrough, exploratory data analysis involves the processes of describing your data (such as by calculating the means and standard deviations of numeric variables, or counting the frequency of categorical variables) and, often, visualizing your data prior to modeling.

In Section 3, we will learn some new functions for retrieving basic network descriptives related to our research question and create a network visualization to help illustrate key findings. Specifically, in this section we’ll learn to:

  1. Examine Basic Descriptives. We focus primarily on actors and edges in this walkthrough, including the edges wights we added in the previous section as well as node degree, and import and fairly intuitive measure of centrality.

  2. Make a Sociogram. Finally, we wrap up the explore phases by learning to plot a network and tweak key elements like the size, shape, and position of nodes and edges to better at communicating key findings.

3a. Examine Basic Descriptives

Many analyses of social networks are primarily descriptive. As Carolyn (2013) notes that these descriptive studies aim either to represent the network’s underlying social structure through data-reduction techniques or to characterize network properties through network measures.

Node Degree

A key structural property of networks is the concept of centralization. A network that is highly centralized is one in which relations are focused on a small number of actors or even a single actor in a network, whereas ties in a decentralized network are diffuse and spread over a number of actors. One of the most common descriptives reported in network studies and a primary measure of centralization is degree.

Degree is the number of ties to and from an ego. In a directed network, in-degree is the number of ties received, whereas out-degree is the number of ties sent.

The {igraph} package has an aptly named function degree() for retrieving degree, in-degree, and out-degree for all actors in a network.

Run the following code to extract measures and save to node_degree which we’ll examine in just a bit:

node_degree <- degree(weighted_network, mode = "all")

Note. We set the mode = argument in this function to “all” which give us the total number of participants that each actor in our network with sent or received a reply.

Let’s take a look at the distribution of node_degree in our network by using R’s built in hist() function for creating histograms. I set the value of breaks =, or bins in our histogram, to 30 since I already know some actors in this network have a very high degree.

hist(node_degree, breaks = 30)

We can see that most actors in the network are connected to very few individuals while a couple actors in this network are connected to a very larger number, nearly 200 and 350 respectively!

Now let’s take a look at the mean and median for node_degree using some other {base} R functions:

mean(node_degree)
median(node_degree)

We see that the mean suggests the participants are, on average, connected to about 8 other participants in the MOOC-Ed, but this is likely heavily skewed by the two individuals with a disproportionate number of connections. The median is probably a better characterization of the typical number of educators a participant has sent or received a reply.

In-Degree

Let’s go ahead and take a look at in-degree next:

in_degree <- degree(weighted_network, mode="in")

hist(in_degree, breaks = 30)
mean(in_degree)
median(in_degree)

Again, most participants received a reply from small number of individuals.

👉 Your Turn

Use the code chunk below to examine the distribution, mean and median of out_degree:

In the space below, write your interpretation of these results.

-

Edge Weights

Finally, let’s also take a look at the distribution, mean and median of the edge weights we added to our graph.

Recall from earlier that the {igraph} package has a unique syntax for accessing node and edge attributes. For edges we use E() and included the name of the network object we want to use, followed by the $ operator to select the attribute.

weights <- E(weighted_network)$weight

hist(weights, breaks = 10)
mean(weights)
median(weights)

It looks like the vast majority or participants either sent or received a reply from just one other participant.

👉 Your Turn

The use of the $ is actually standard across R and a very useful operator.

Use the code chunk below to create a histogram and calculate the mean and median from the edge weighs created earlier in the Add Edge Weights section by using the edge_weights data frame, the $ operator, and column n which contains the counts for each unique edge.

Are these results consistent with our summary of edge weights we created above?

-

3b. Make a Sociogram

If you recall from our 1a. Review the Research section, one of the defining characteristics of the social network perspective is its use of graphic imagery to represent actors and their relations with one another. To emphasize this point, Carolyn (2013) reported that:

The visualization of social networks has been a core practice since its foundation more than 90 years ago and remains a hallmark of contemporary social network analysis. 

Network visualization can be used for a variety of purposes, ranging from highlighting key actors to even serving as works of art. This excellent figure from Katya Ognyanova’s also excellent tutorial on Static and Dynamic Network Visualization with R helps illustrate the variety of goals a good network visualization can accomplish:

These visual representations of the actors and their relations, i.e. the network, are called a sociogram. Actors who are most central to the network, such as those with higher node degrees, are usually placed in the center of the sociogram and their ties are placed near them. As we’ll see in just a bit, those two actors with hundreds of ties will be placed by most graph layout algorithms in the center of the graph.

For Unit 1, we’ll be using the plot() function from R’s built in {graphics} package to make a sociogram.

Let’s run the code and see what we get without any tweaking and see what the plot function produces:

plot(weighted_network)

If this had been a smaller network like one generated from a teacher professional development workshop, this might have been useful, but for large networks like our MOOC-Ed discussion forums, this doesn’t communicate much. In fact, it’s visualizations like these that give sociograms the unflattering nickname of “hair ball” plots.

Fortunately, the {igraph} package includes a plethora of plotting parameters for improving the layout and visual design of network graphs!

There are many ways to modify vertices and edges in a sociogram to improve readability. Up to four attributes of each actor can be layered onto the sociogram by altering the color, shape, label, and size of the symbol. And attributes for edges can be represented in a range of ways as well.

Remove Labels

One quick fix is to simply remove the labels by adding the vertex.label = argument and setting it to NA.

Since the number labels don’t provide much useful information, let’s go ahead and remove them:

plot(weighted_network,
     vertex.label = NA)

We can now at least see the nodes, or vertices, but with 445 participants in the forums, many are masked by the default size of each node.

Change vertex size

By default, the size of nodes is 15. Let’s add the vertex.size = argument and change that to 1:

plot(weighted_network,
     vertex.label = NA,
     vertex.size = 1)

A little better, but let’s use the node_degree we calculated to emphasize those wiht greater connections in the course by substitute node_degree for a specific value.

plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree)

Whoops! This certainly emphasizes the disproportionate number of ties among these two participants, but not quite what we’re going for.

Since node_degree is just a list of values for each node we can treat it like a number. Let’s divide that by 10 to reduce the relative size:

plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree/10)

That’s better, and helps highlight our two main actors without overshadowing the rest, but those arrows are definitely an eyesore.

Reduce arrow size

Let’s add the edge.arrow.size = argument and dramatically reduce:

plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree*.1,
     edge.arrow.size = .04)

Much better, now let’s deal with the size of the edges.

Adjust Edge Width

We can add the edge.width = argument to help minimize edge overlap yet still make them visible. This is a bit of trial and error but let’s give .2 a try since the default is 1:

plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree*.05,
     edge.arrow.size = .04,
     edge.width = .2)

Note that we could also set edge.with = to the weight of each edge, similar to how we used degree for the size of each node.

Let’s give that a try:

plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree*.1,
     edge.arrow.size = .04,
     edge.width = E(weighted_network)$weight)

Not much of an improvement, if at all, given how many edges are in our network.

Let’s try dividing that weight by 5 similar to reduce like with did with the vertex.size = argument:

plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree*.05,
     edge.arrow.size = .05,
     edge.width = E(weighted_network)$weight/5)

Better, but since we know most edges have a weight of 1 there really isn’t too much to work with here.

Let’s move on to changing graph layout!

Change Layout

One of the major advances in visualization since the first hand-drawn sociograms developed by Jacob Moreno (1934) to represent relations among children in school is the use of software and algorithms to automatically layout networks on a grid.

There are may different layout methods, but we’ll start with the Fruchterman-Reingold (FR) layout, which is one of the most used layout algorithms for network visualization. These types of force-directed algorithms generally work well with large networks and try to layout graphs in “an aesthetically-pleasing way” by making edges roughly equal in length and minimizing overlap.

Let give the FR layout a try by using the layout = argument and specifying layout_with_fr:

plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree*.05,
     edge.arrow.size = .05,
     edge.width = E(weighted_network)$weight/5,
     layout = layout_with_fr)

By default, {igraph} uses layout_nicely, a smart function that chooses a layout based on the graph. Given the similarity with our previous graph, I’m assuming it chose the the FR layout as well.

Let’s try one more just for fun:


plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree*.05,
     edge.arrow.size = .05,
     edge.width = E(weighted_network)$weight/5,
     layout = layout_in_circle)

Interesting but not terribly useful!

There are many other igraph layout functions, some more useful than others depending on the context. We’ve only scratched the surface of what’s possible with network plotting but hopefully this have given you a sense of what required to avoid the dreaded “hair ball” plot and create a network viz that communicates something useful.

👉 Your Turn

Try modifying the code below by tweaking the included arguments/parameters or adding new arguments/parameters to make our plot either more “aesthetically pleasing” or more purposeful in what it’s trying to communicate.

You’re also welcome to try out some of the other graphing options from from Katya Ognyanova’s tutorial on Static and Dynamic Network Visualization with R.

There are no right or wrong answers, just have some fun trying out different approaches!

plot(weighted_network,
     vertex.label = NA,
     vertex.size = node_degree*.05,
     edge.arrow.size = .05,
     edge.width = E(weighted_network)$weight/5,
     layout = layout_with_fr)

🧶 Knit & Check ✅

Congrats! You made it to the end of the Explore section and are ready to learn a little about network modeling! Before proceeding further, knit your document and check to see if you encounter any errors.

4. MODEL

As highlighted in Chapter 3 of Data Science in Education Using R, the Model step of the data science process entails “using statistical models, from simple to complex, to understand trends and patterns in the data.” The authors note that while descriptive statistics and data visualization during the Explore step can help us to identify patterns and relationships in our data, statistical models can be used to help us determine if relationships, patterns and trends are actually meaningful.

We will not explore the use of models for SNA until Unit 3, but recall from A Social Network Perspective in MOOC-Eds was guided by the following questions:

  1. What are the patterns of peer interaction and the structure of peer networks that emerge over the course of a MOOC-Ed?

  2. To what extent do participant and network attributes (e.g., homophily, reciprocity, transitivity) account for the structure of these networks?

  3. To what extent do these networks result in the co-construction of new knowledge?

To address Question 1, actors in the network were categorized into distinct mutually exclusive groups using the core-periphery and regular equivalence functions of UCINET. The former used the CORR algorithm to divide the network into actors that are part of a densely connected subgroup, or “core,” from those that are part of the sparsely connected periphery. Regular equivalence employs the REGE blockmodeling algorithm to partition, or group, actors in the network based on the similarity of their ties to others with similar ties. In essence, blockmodeling provides a systematic way for categorizing educators based on the ways in which they interacted with peers.

As we saw upon just a basic visual inspection of our network during the Explore section, there was a small core of highly connected participants surrounded by those on the “periphery,” or edge, of the network with very few connections. In the DLT 2 course, those on the periphery made up roughly 90% of network! The study also found relatively high levels of reciprocation, but also found that roughly a quarter of participants were characterized as “brodcasters” – educators who initiated a discussion thread, but neither reciprocated with those who replied, nor posted to threads initiated by others.

To address Question 2, this study use the exponential family of random graph models (ERGM; also known as p* models), which provide a statistical approach to network modeling that addresses the complex dependencies within networks. ERGMs predict network ties and determine the statistical likelihood of a given network structure, based on an assumed dependency structure, the attributes of the individuals (e.g., gender, popularity, location, previous ties) and prior states of the network.

👉 Your Turn

Recall from the 1a. Review the Research that you were asked to identify two “node attributes” from the dataset that might be useful for predicting participants who may be more engaged or central to the network.

Take look at page 276 of A social network perspective on peer supported learning in MOOCs for educators. Were your predictions correct?

-


5. COMMUNICATE

The final step in our workflow/process is sharing the results of analysis with wider a audience. Krumm et al. (2018) have outline the following 3-step process for communicating with education stakeholders what you have learned through analysis:

  1. Select. Communicating what one has learned involves selecting among those analyses that are most important and most useful to an intended audience, as well as selecting a form for displaying that information, such as a graph or table in static or interactive form, i.e. a “data product.”

  2. Polish. After creating initial versions of data products, research teams often spend time refining or polishing them, by adding or editing titles, labels, and notations and by working with colors and shapes to highlight key points.

  3. Narrate. Writing a narrative to accompany the data products involves, at a minimum, pairing a data product with its related research question, describing how best to interpret the data product, and explaining the ways in which the data product helps answer the research question.

For your Independent Analysis assignment for Unit 1 next week, you’ll be creating either a simple report or slide deck using an R Markdown document just like this to share out some key findings from our analysis. Regardless of whether you plan to talk us through your analysis and findings with a presentation or walk us through with a brief written report, your presentation or report should address the following questions:

  1. Purpose. What question or questions are guiding your analysis? What did you hope to learn by answering these questions and why should your audience care about your findings?

  2. Methods. What data did you selected for analysis? What steps did you take took to prepare your data for analysis and what techniques you used to analyze your data? These should be fairly explicit with your embedded code.

  3. Findings. What did you ultimately find? How do your “data products” help to illustrate these findings? What conclusions can you draw from your analysis?

  4. Discussion. What were some of the strengths and weaknesses of your analysis? How might your audience use this information? How might you revisit or improve upon this analysis in the future?

Examples and Templates

You can view an example presentation from ECI 588 here: <https://sbkellogg.github.io/eci-588/unit-1/unit-1-product.html>

And use my R Markdown presentation file as a template if you like: <https://github.com/sbkellogg/eci-588/blob/main/unit-1/unit-1-product.Rmd>

👉 Your Turn

Now that you’ve become more familiar with this dataset and the social network perspective, what other aspects of this dataset, or a dataset you are interested in exploring, could you investigate?

-

What specific research questions might you ask that would be helpful for being understanding and improving learning, or the context in which the data is collected?

-

🧶 Knit & Check ✅

Congrats! You’ve finished the Unit 1 Guided Walkthrough and are ready for some independent analysis next week!

To complete this assignment, knit your document and send me an email at sbkellog@ncsu.edu letting me know you’re all set.

REFERENCES

Carolan, Brian. 2014. “Social Network Analysis and Education: Theory, Methods & Applications.” https://doi.org/10.4135/9781452270104.
LS0tCnRpdGxlOiAnQXR0cmlidXRlcywgRWRnZS1MaXN0cywgJiBpZ3JhcGhzLCBPaCBNeSEnCnN1YnRpdGxlOiAnU05BIExlYXJuaW5nIExhYiAxLjEnCmF1dGhvcjogIkxBU0VSIEluc3RpdHV0ZSIKZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCclQiAlZSwgJVknKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6IHllcwpiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIyAxLiBQUkVQQVJFCgpBbHRob3VnaCBzb2NpYWwgbmV0d29yayBhbmFseXNpcyAoU05BKSBhbmQgaXRzIGVkdWNhdGlvbmFsIGFudGVjZWRlbnRzIGRhdGUgYmFjayB0byB0aGUgZWFybHkgMTkwMHMsIHB1YmxpYyBhbmQgc2Nob2xhcmx5IGludGVyZXN0IGluIHNvY2lhbCBuZXR3b3JrIGFuYWx5c2lzIGRpZCBub3QgcmVhbGx5IHRha2Ugb2ZmIHVudGlsIHRoZSB0dXJuIG9mIHRoZSBjZW50dXJ5W0BjYXJvbGFuMjAxNF0uIEFwcGxpY2F0aW9ucyBvZiBzb2NpYWwgbmV0d29yayBhbmFseXNpcyBoYXMgZXhwZXJpZW5jZWQgZXhwb25lbnRpYWwgZ3Jvd3RoLCBhbmQgYWNyb3NzIGEgd2lkZSByYW5nZSBvZiBwaGVub21lbmEsIGFzIGRvY3VtZW50ZWQgYnkgYSBudW1iZXIgb2Ygc3R1ZGllcy4KCkRlc3BpdGUgZWR1Y2F0aW9uYWwgcmVzZWFyY2ggbGFnZ2luZyBiZWhpbmQgb3RoZXIgZmllbGRzLCBhbiBpbmNyZWFzZSBpbiB0aGUgdXNlIG9mIGRpZ2l0YWwgbGVhcm5pbmcgcmVzb3VyY2VzIGFuZCBkYXRhIGNvbGxlY3RlZCBieSB0aGVzZSBlZHVjYXRpb25hbCB0ZWNobm9sb2dpZXMsIGFzIHdlbGwgYXMgaW1wcm92ZWQgYWNjZXNzIHRvIHRyYWluaW5nIGFuZCB0b29scyBmb3IgY29sbGVjdGluZyBhbmQgYW5hbHl6aW5nIHRoZXNlIGRhdGEsIGhhcyBncmVhdGx5IGZhY2lsaXRhdGVkIHRoZSBhcHBsaWNhdGlvbiBvZiBuZXR3b3JrIGFuYWx5c2lzIHRvIHRlYWNoaW5nIGFuZCBsZWFybmluZy4KCioqU05BIE1vZHVsZSAxOiBUaGUgU29jaWFsIE5ldHdvcmsgUGVyc3BlY3RpdmUgYW5kIE1PT0MtRWRzKiogaXMgZGVzaWduZWQgdG8gcHJlcGFyZSBMQVNFUiBJbnN0aXR1dGUgc2Nob2xhcnMgZm9yIGNvbGxlY3RpbmcsIHByb2Nlc3NpbmcsIGFuZCBhbmFseXppbmcgcmVsYXRpb25hbCBkYXRhIGZyb20gYSByZWFsLXdvcmxkIHN0dWR5LiBTcGVjaWZpY2FsbHksIHRoZSB0aHJlZSBMZWFybmluZyBMYWJzIHRoYXQgbWFrZSB1cCB0aGlzIG1vZHVsZSBhZGRyZXNzIHRoZSBmb2xsb3dpbmcgdG9waWNzOgoKLSAgICoqTGVhcm5pbmcgTGFiIDE6IEF0dHJpYnV0ZXMsIEVkZ2UtTGlzdHMsICYgaWdyYXBocywgT2ggTXkhKiogSW4gb3VyIGZpcnN0IGxhYiwgd2UgcHJlcGFyZSBmb3IgYW5hbHlzaXMgYnkgZ2FpbmluZyBzb21lIGNvbnRleHQgYWJvdXQgb3VyIGRhdGE7IGxlYXJuaW5nIGhvdyB0byB3cmFuZ2xlIG5ldHdvcmsgZGF0YSBzdHJ1Y3R1cmVzOyBhbmQgZXhhbWluaW5nIG5ldHdvcmsgZGVzY3JpcHRpdmVzLgoKLSAgICoqTGVhcm5pbmcgTGFiIDI6IFNvY2lvZ3JhbXMgJiBOZXR3b3JrIFZpc3VhbGl6YXRpb24uKirCoEZvciBvdXIgc2Vjb25kIGxhYiwgd2UgZGlzY3VzcyB0aGUgZ29hbHMgb2YgbmV0d29yayB2aXN1YWxpemF0aW9uIGFuZCB3YXlzIHRvIGV4cGxvcmUgZGF0YSBuZXR3b3JrIGRhdGEgdmlzdWFsbHkuCgotICAgKipMZWFybmluZyBMYWIgMzogQ29yZXMsIENsaXF1ZXMsICYgQ29tbXVuaXRpZXMuKirCoFdlIHdyYXAgdXAgU05BIE1vZHVsZSAxIHdpdGggcXVpY2sgbG9vayBhdCBib3RoIGJvdHRvbXMtdXAgYW5kIHRvcGMtZG93biAuwqAKCiMjIyAxYS4gUmV2aWV3IHRoZSBSZXNlYXJjaAoKSW4gU29jaWFsIE5ldHdvcmsgQW5hbHlzaXMgYW5kIEVkdWNhdGlvbjogVGhlb3J5LCBNZXRob2RzICYgQXBwbGljYXRpb25zLCBAY2Fyb2xhbjIwMTQgbm90ZXMgdGhhdDoKCj4gdGhlICoqc29jaWFsIG5ldHdvcmsgcGVyc3BlY3RpdmUqKiBpcyBvbmUgY29uY2VybmVkIHdpdGggdGhlIHN0cnVjdHVyZSBvZiByZWxhdGlvbnMgYW5kIHRoZSBpbXBsaWNhdGlvbiB0aGlzIHN0cnVjdHVyZSBoYXMgb24gaW5kaXZpZHVhbCBvciBncm91cCBiZWhhdmlvciBhbmQgYXR0aXR1ZGVzCgpNb3JlIHNwZWNpZmljYWxseSwgQ2Fyb2x5biBjaXRlcyB0aGUgZm9sbG93aW5nIGZvdXIgZmVhdHVyZXMgdXNlZCBieSBGcmVlbWFuICgyMDA0KSB0byBkZWZpbmUgdGhlIHNvY2lhbCBuZXR3b3JrIHBlcnNwZWN0aXZlOgoKMS4gIFNvY2lhbCBuZXR3b3JrIGFuYWx5c2lzIGlzICoqbW90aXZhdGVkIGJ5IGEgcmVsYXRpb25hbCBpbnR1aXRpb24qKiBiYXNlZCBvbiB0aWVzIGNvbm5lY3Rpbmcgc29jaWFsIGFjdG9ycy4KCjIuICBJdCBpcyBmaXJtbHkgKipncm91bmRlZCBpbiBzeXN0ZW1hdGljIGVtcGlyaWNhbCBkYXRhKiouCgozLiAgSXQgKiptYWtlcyoqICoqdXNlIG9mIGdyYXBoaWMgaW1hZ2VyeSoqIHRvIHJlcHJlc2VudCBhY3RvcnMgYW5kIHRoZWlyIHJlbGF0aW9ucyB3aXRoIG9uZSBhbm90aGVyLgoKNC4gIEl0ICoqcmVsaWVzKiogKipvbioqICoqbWF0aGVtYXRpY2FsIGFuZC9vciBjb21wdXRhdGlvbmFsIG1vZGVscyoqIHRvIHN1Y2NpbmN0bHkgcmVwcmVzZW50IHRoZSBjb21wbGV4aXR5IG9mIHNvY2lhbCBsaWZlLgoKRm9yIFVuaXQgMSwgb3VyIHdhbGt0aHJvdWdoIHdpbGwgYmUgZ3VpZGVkIGJ5IHByZXZpb3VzIHJlc2VhcmNoIGFuZCBldmFsdWF0aW9uIHdvcmsgY29uZHVjdGVkIGJ5IHRoZSBGcmlkYXkgSW5zdGl0dXRlIGZvciBFZHVjYXRpb25hbCBJbm5vdmF0aW9uIGFzIHBhcnQgb2YgdGhlIE1hc3NpdmVseSBPcGVuIE9ubGluZSBDb3Vyc2VzIGZvciBFZHVjYXRvcnMgKE1PT0MtRWQpIGluaXRpYXRpdmUuIFRoZSBzdHVkeSBpbnRyb2R1Y2VkIG5leHQgYW5kIHRoZSBoYW5kcy1vbiBhbmFseXNpcyB3aXRoIFIgaW4gdGhpcyB3YWxrdGhyb3VnaCB3aWxsIGhlbHAgdG8gaWxsdXN0cmF0ZSB0aGVzZSBmb3VyIGRlZmluaW5nIGZlYXR1cmVzIG9mIHRoZSBzb2NpYWwgbmV0d29yayBwZXJzcGVjdGl2ZS4KCiMjIyMgQSBTb2NpYWwgTmV0d29yayBQZXJzcGVjdGl2ZSBpbiBNT09DLUVkcwoKIVtdKGltZy9pcnJvZGwtYXJ0aWNsZS5wbmcpe3dpZHRoPSIzMCUifQoKS2VsbG9nZywgUy4sIEJvb3RoLCBTLiwgJiBPbGl2ZXIsIEsuICgyMDE0KS4gW0Egc29jaWFsIG5ldHdvcmsgcGVyc3BlY3RpdmUgb24gcGVlciBzdXBwb3J0ZWQgbGVhcm5pbmcgaW4gTU9PQ3MgZm9yIGVkdWNhdG9yc10oaHR0cHM6Ly9naXRodWIuY29tL3Nia2VsbG9nZy9lY2ktNTg5L2Jsb2IvbWFpbi91bml0LTEvbGl0L3NuYV9tb29jX2lycm9kbF9iamV0X2FydGljbGVzLnBkZikuwqAqSW50ZXJuYXRpb25hbCBSZXZpZXcgb2YgUmVzZWFyY2ggaW4gT3BlbiBhbmQgRGlzdHJpYnV0ZWQgTGVhcm5pbmcqLMKgKjE1Kig1KSwgMjYzLTI4OS4KCiMjIyMjIFJlc2VhcmNoIENvbnRleHQKCkluIHRoZSBzcHJpbmcgb2YgMjAxMywgVGhlIEZyaWRheSBJbnN0aXR1dGUgbGF1bmNoZWQgdGhlIE1PT0MtRWQgSW5pdGlhdGl2ZSB0byBleHBsb3JlIHRoZSBwb3RlbnRpYWwgb2YgZGVsaXZlcmluZyBwZXJzb25hbGl6ZWQsIGhpZ2gtcXVhbGl0eSBwcm9mZXNzaW9uYWwgZGV2ZWxvcG1lbnQgdG8gZWR1Y2F0b3JzIGF0IHNjYWxlIChLbGVpbWFuIGV0IGFsLiwgMjAxMykuIEluIGNvbGxhYm9yYXRpb24gd2l0aCB0aGUgQWxsaWFuY2UgZm9yIEV4Y2VsbGVudCBFZHVjYXRpb24sIHRoZSBGcmlkYXkgSW5zdGl0dXRlIGxhdW5jaGVkIHRoaXMgaW5pdGlhdGl2ZSB3aXRoIGEgNi13ZWVrIHBpbG90IGNvdXJzZSBjYWxsZWQgUGxhbm5pbmcgZm9yIHRoZSBEaWdpdGFsIExlYXJuaW5nIFRyYW5zaXRpb24gaW4gSy0xMiBTY2hvb2xzIChETFQgMSksIHdoaWNoIHdhcyBvZmZlcmVkIGFnYWluIGluIFNlcHRlbWJlciAyMDEzIChETFQgMikuIFRoaXMgY291cnNlIHdhcyBkZXNpZ25lZCB0byBoZWxwIHNjaG9vbCBhbmQgZGlzdHJpY3QgbGVhZGVycyBwbGFuIGFuZCBpbXBsZW1lbnQgSy0xMiBkaWdpdGFsIGxlYXJuaW5nIGluaXRpYXRpdmVzLgoKQWNhZGVtaWNzLCBhcyB3ZWxsIGFzIHB1bmRpdHMgZnJvbSB0cmFkaXRpb25hbCBhbmQgbmV3IG1lZGlhLCBoYXZlIHJhaXNlZCBhIG51bWJlciBvZiBjb25jZXJucyBhYm91dCBNT09DcywgaW5jbHVkaW5nIHRoZSBsYWNrIG9mIGluc3RydWN0aW9uYWwgYW5kIHNvY2lhbCBzdXBwb3J0cy4gQW1vbmcgdGhlIGNvcmUgZGVzaWduIHByaW5jaXBsZXMgb2YgTU9PQy1FZHMgYXJlIGNvbGxhYm9yYXRpb24gYW5kIHBlZXItc3VwcG9ydGVkIGxlYXJuaW5nLiBJdCBpcyBhbiBhc3N1bXB0aW9uIG9mIHRoaXMgc3R1ZHkgdGhhdCBjaGFsbGVuZ2VzIGFyaXNpbmcgZm9ybSB0aGlzIHByb2JsZW0gb2Ygc2NhbGUgY2FuIGJlIGFkZHJlc3NlZCBieSBsZXZlcmFnaW5nIHRoZXNlIG1hc3NpdmUgbnVtYmVycyB0byBkZXZlbG9wIHJvYnVzdCBvbmxpbmUgbGVhcm5pbmcgY29tbXVuaXRpZXMuCgpUaGlzIG1peGVkLW1ldGhvZHMgY2FzZSBzdHVkeSB1c2VkIGJvdGggU05BIGFuZCBxdWFsaXRhdGl2ZSBtZXRob2RzIHRvIGJldHRlciB1bmRlcnN0YW5kIHBlZXIgc3VwcG9ydCBpbiBNT09DLUVkcyB0aHJvdWdoIGFuIGV4YW1pbmF0aW9uIG9mIHRoZSBjaGFyYWN0ZXJpc3RpY3MsIG1lY2hhbmlzbXMsIGFuZCBvdXRjb21lcyBvZiBwZWVyIG5ldHdvcmtzLiBGaW5kaW5ncyBmcm9tIHRoaXMgc3R1ZHkgZGVtb25zdHJhdGUgdGhhdCBldmVuIHdpdGggdGVjaG5vbG9neSBhcyBiYXNpYyBhcyBhIGRpc2N1c3Npb24gZm9ydW0sIE1PT0NzIGNhbiBiZSBsZXZlcmFnZWQgdG8gZm9zdGVyIHRoZXNlIG5ldHdvcmtzIGFuZCBmYWNpbGl0YXRlIHBlZXItc3VwcG9ydGVkIGxlYXJuaW5nLiBBbHRob3VnaCB0aGlzIHN0dWR5IHdhcyBsaW1pdGVkIHRvIHR3byB1bmlxdWUgY2FzZXMgYWxvbmcgdGhlIHdpZGUgc3BlY3RydW0gb2YgTU9PQ3MsIHRoZSBtZXRob2RzIGFwcGxpZWQgcHJvdmlkZSBvdGhlciByZXNlYXJjaGVycyB3aXRoIGFuIGFwcHJvYWNoIGZvciBiZXR0ZXIgdW5kZXJzdGFuZGluZyB0aGUgZHluYW1pYyBwcm9jZXNzIG9mIHBlZXIgc3VwcG9ydGVkIGxlYXJuaW5nIGluIE1PT0NzLgoKIyMjIyMgRGF0YSBTb3VyY2VzCgoqKk1PT0MtRWQgcmVnaXN0cmF0aW9uIGZvcm0uKiogQWxsIHBhcnRpY2lwYW50cyBjb21wbGV0ZWQgYSByZWdpc3RyYXRpb24gZm9ybSBmb3IgZWFjaCBNT09DLUVkIGNvdXJzZS4gVGhlIHJlZ2lzdHJhdGlvbiBmb3JtIGNvbnNpc3RzIG9mIHNlbGYtcmVwb3J0ZWQgZGVtb2dyYXBoaWMgZGF0YSwgaW5jbHVkaW5nIGluZm9ybWF0aW9uIHJlbGF0ZWQgdG8gdGhlaXIgcHJvZmVzc2lvbmFsIHJvbGUgYW5kIHdvcmsgc2V0dGluZywgeWVhcnMgb2YgZXhwZXJpZW5jZSBpbiBlZHVjYXRpb24sIGFuZCBwZXJzb25hbCBsZWFybmluZyBnb2Fscy4KCioqTU9PQy1FZCBkaXNjdXNzaW9uIGZvcnVtcy4qKiBBbGwgcGVlciBpbnRlcmFjdGlvbiwgaW5jbHVkaW5nIHBlZXIgZGlzY3Vzc2lvbiwgZmVlZGJhY2ssIGFuZCByZWFjdGlvbnMgKGUuZy4sIGxpa2VzKSwgdGFrZSBwbGFjZSB3aXRoaW4gdGhlIGZvcnVtIGFyZWEgb2YgTU9PQy1FZHMsIHdoaWNoIGFyZSBwb3dlcmVkIGJ5IFZhbmlsbGEgRm9ydW1zLiBCZWNhdXNlIG9mIHRoZSBzcGVjaWZpYyBmb2N1cyBvbiBwZWVyIHN1cHBvcnRlZCBsZWFybmluZywgcG9zdGluZ3MgdG8gb3IgZnJvbSBjb3Vyc2UgZmFjaWxpdGF0b3JzIGFuZCBzdGFmZiB3ZXJlIHJlbW92ZWQgZnJvbSB0aGUgZGF0YSBzZXQuIEZpbmFsbHksIGFuYWx5c2VzIGRlc2NyaWJlZCBiZWxvdyBleGNsdWRlIG1vcmUgcGFzc2l2ZSBmb3JtcyBvZiBpbnRlcmFjdGlvbnMgKGkuZS4sIHJlYWQgYW5kIHJlYWN0aW9uIGxvZ3MpLCBhbmQgaW5jbHVkZSBvbmx5IHBvc3RpbmdzIGFtb25nIHBlZXJzLgoKRm9yIG91ciBVbml0IDEgd2Fsa3Rocm91Z2gsIHdlJ2xsIHRha2UgYSBsb29rIGF0IGRhdGEgZnJvbSB0aGUgb3JpZ2luYWwgRGlnaXRhbCBMZWFybmluZyBUcmFuc2l0aW9uIGluIEstMTIgU2Nob29scyAoRExUIDEpIHRoYXQgd2FzIG5vdCBpbmNsdWRlZCBpbiB0aGlzIHN0dWR5IHRvIGFsbG93IGZvciBjb21wYXJpc29ucyB0byB0aGUgZmluZGluZ3MgaW4gdGhpcyBzdHVkeS4gRm9yIHlvdXIgaW5kZXBlbmRlbnQgYW5hbHlzaXMgbmV4dCB3ZWVrLCB5b3UgbWF5IHdhbnQgdG8gY29uc2lkZXIgd29ya2luZyB3aXRoIHRoZSBETFQgMiBkYXRhIHRvIHNlZSBpZiB5b3UgY2FuIHJlcGxpY2F0ZSBzb21lIG9mIHRoZSBmaW5kaW5ncyBmcm9tIHRoaXMgcGFwZXIhCgoqKk5vdGUqKjogSW4gdGhlIGRhdGEgd2UncmUgdXNpbmcsIGluc3RydWN0b3JzIGhhdmUgbm90IHlldCBiZWVuIHJlbW92ZWQgYW5kIG9ubHkgZGlyZWN0IHJlcGxpZXMgdG8gZm9ydW0gcG9zdHMgaGF2ZSBiZWVuIGluY2x1ZGVkLCB0aG91Z2ggIndlYWtlciIgdGllcyBsaWtlIHJlYWN0aW9ucyB3aXRoIGVtb3RpY29ucyBhbmQgZXZlbiB2aWV3cyBvZiBwb3N0cyB3ZXJlIGNhcHR1cmVkIGluIHRoaXMgc3R1ZHkuCgojIyMjICoq8J+RiSBZb3VyIFR1cm4qKiAqKuKktSoqCgpUYWtlIGEgcXVpY2sgbG9vayBhdCB0aGUgKkRlc2NyaXB0aW9uIG9mIHRoZSBEYXRhc2V0KiBzZWN0aW9uIGZyb20gdGhlIFtNYXNzaXZlbHkgT3BlbiBPbmxpbmUgQ291cnNlIGZvciBFZHVjYXRvcnMgKE1PT0MtRWQpIG5ldHdvcmsgZGF0YXNldF0oaHR0cHM6Ly9naXRodWIuY29tL3Nia2VsbG9nZy9lY2ktNTg5L2Jsb2IvbWFpbi91bml0LTEvbGl0L2JqZXRfMTIzMTJfUmV2LnBkZikgQkpFVCBhcnRpY2xlIGFuZCB0aGUgYWNjb21wYW55aW5nIGRhdGEgc2V0cyBzdG9yZWQgb24gW0hhcnZhcmQgRGF0YXZlcnNlXShodHRwczovL2RhdGF2ZXJzZS5oYXJ2YXJkLmVkdS9kYXRhc2V0LnhodG1sP3BlcnNpc3RlbnRJZD1kb2k6MTAuNzkxMC9EVk4vWlpIM1VCKSB0aGF0IHdlJ2xsIGJlIHVzaW5nIGZvciB0aGlzIHdhbGt0aHJvdWdoLgoKSW4gdGhlIHNwYWNlIGJlbG93LCB0eXBlIGEgYnJpZWYgcmVzcG9uc2UgdG8gdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6CgoxLiAgV2hhdCB3ZXJlIHNvbWUgb2YgdGhlIHN0ZXBzIG5lY2Vzc2FyeSB0byBjb25zdHJ1Y3QgdGhpcyBkYXRhc2V0PwoKICAgIC0gICAKCjIuICBXaGF0IHR3byAibm9kZSBhdHRyaWJ1dGVzIiBmcm9tIHRoZSBkYXRhc2V0IHRoYXQgbWlnaHQgYmUgdXNlZnVsIGZvciBwcmVkaWN0aW5nIHBhcnRpY2lwYW50cyB3aG8gbWF5IGJlIG1vcmUgZW5nYWdlZCBvciBjZW50cmFsIHRvIHRoZSBuZXR3b3JrPyBXaHkgZGlkIHlvdSBzZWxlY3QgdGhvc2UgdHdvPwoKICAgIC0gICAKCjMuICBXaGF0IGVsc2UgZG8geW91IG5vdGljZS93b25kZXIgYWJvdXQgdGhpcyBkYXRhc2V0PwoKICAgIC0gICAKCiMjIyAxYi4gSWRlbnRpZnkgYSBRdWVzdGlvbihzKQoKQSBTb2NpYWwgTmV0d29yayBQZXJzcGVjdGl2ZSBvbiBQZWVyIFN1cHBvcnRlZCBMZWFybmluZyBpbiBNT09DLUVkcyB3YXMgZnJhbWVkIGJ5IHRocmVlIHByaW1hcnkgcmVzZWFyY2ggcXVlc3Rpb25zIHJlbGF0ZWQgdG8gcGVlciBzdXBwb3J0ZWQgbGVhcm5pbmc6CgoxLiAgV2hhdCBhcmUgdGhlIHBhdHRlcm5zIG9mIHBlZXIgaW50ZXJhY3Rpb24gYW5kIHRoZSBzdHJ1Y3R1cmUgb2YgcGVlciBuZXR3b3JrcyB0aGF0IGVtZXJnZSBvdmVyIHRoZSBjb3Vyc2Ugb2YgYSBNT09DLUVkPwoKMi4gIFRvIHdoYXQgZXh0ZW50IGRvIHBhcnRpY2lwYW50IGFuZCBuZXR3b3JrIGF0dHJpYnV0ZXMgKGUuZy4sIGhvbW9waGlseSwgcmVjaXByb2NpdHksIHRyYW5zaXRpdml0eSkgYWNjb3VudCBmb3IgdGhlIHN0cnVjdHVyZSBvZiB0aGVzZSBuZXR3b3Jrcz8KCjMuICBUbyB3aGF0IGV4dGVudCBkbyB0aGVzZSBuZXR3b3JrcyByZXN1bHQgaW4gdGhlIGNvLWNvbnN0cnVjdGlvbiBvZiBuZXcga25vd2xlZGdlPwoKRm9yIG91ciB2ZXJ5IGZpcnN0IHdhbGt0aHJvdWdoLCB3ZSBhcmUgZ29pbmcgdG8gZm9jdXMgZXhjbHVzaXZlbHkgb24gUlExIGZyb20gdGhlIG9yaWdpbmFsIHN0dWR5IGFuZCBvdXIgcXVlc3Rpb24gb2YgaW50ZXJlc3QgYWJvdXQgb3VyIGRpc2N1c3Npb24gbmV0d29yayBpczoKCj4gVG8gd2hhdCBleHRlbnQsIGRpZCBlZHVjYXRvcnMgZW5nYWdlIHdpdGggb3RoZXIgcGFydGljaXBhbnRzIGluIHRoZSBkaXNjdXNzaW9uIGZvcnVtcz8KCiMjIyMgKirwn5GJIFlvdXIgVHVybioqICoq4qS1KioKCkJhc2VkIG9uIHdoYXQgeW91IGtub3cgYWJvdXQgbmV0d29ya3MgYW5kIHRoZSBjb250ZXh0IHNvIGZhciwgd2hhdCBvdGhlciByZXNlYXJjaCBxdWVzdGlvbnMgbWlnaHQgYXNrIHdlIGFzayBpbiB0aGlzIGNvbnRleHQgdGhhdCBhIHNvY2lhbCBuZXR3b3JrIHBlcnNwZWN0aXZlIG1pZ2h0IGJlIGFibGUgdG8gYW5zd2VyPwoKSW4gdGhlIHNwYWNlIGJlbG93LCB0eXBlIGEgYnJpZWYgcmVzcG9uc2UgdG8gdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6CgpcLQoKV2UnbGwgcmV2aXNpdCB5b3VyIHJlc3BvbnNlIHRvd2FyZHMgdGhlIGVuZCBhbmQgcHJvdmlkZSBhbiBvcHBvcnR1bml0eSB0byByZWZpbmUgeW91ciByZXNlYXJjaCBxdWVzdGlvbiBhZnRlciB5b3Uga25vdyB0aGUgZGF0YSBhIGxpdHRsZSBiZXR0ZXIuCgojIyMgMWMuIExvYWQgTGlicmFyaWVzCgpBcyBoaWdobGlnaHRlZCBpbiBbQ2hhcHRlciA2IG9mIERhdGEgU2NpZW5jZSBpbiBFZHVjYXRpb24gVXNpbmcgUl0oaHR0cHM6Ly9kYXRhc2NpZW5jZWluZWR1Y2F0aW9uLmNvbS9jMDYuaHRtbCNjMDZwKSAoRFNJRVVSKToKCj4gUGFja2FnZXMgYXJlIHNoYXJlYWJsZSBjb2xsZWN0aW9ucyBvZiBSIGNvZGUgdGhhdCBjYW4gY29udGFpbiBmdW5jdGlvbnMsIGRhdGEsIGFuZC9vciBkb2N1bWVudGF0aW9uLiBQYWNrYWdlcyBpbmNyZWFzZSB0aGUgZnVuY3Rpb25hbGl0eSBvZiBSIGJ5IHByb3ZpZGluZyBhY2Nlc3MgdG8gYWRkaXRpb25hbCBmdW5jdGlvbnMgdG8gc3VpdCBhIHZhcmlldHkgb2YgbmVlZHMuCgpZb3UgY2FuIGFsd2F5cyBjaGVjayB0byBzZWUgd2hpY2ggcGFja2FnZXMgaGF2ZSBhbHJlYWR5IGJlZW4gaW5zdGFsbGVkIGFuZCBsb2FkZWQgaW50byBSU3R1ZGlvIENsb3VkIGJ5IGxvb2tpbmcgYXQgdGhlIHRoZSBGaWxlcywgUGxvdHMsICYgUGFja2FnZXMgUGFuZSBpbiB0aGUgbG93ZXIgcmlnaHQgaGFuZCBjb3JuZXIgb2YgUlN0dWRpbyBhcyBzaG93biBpbiB0aGUgZm9sbG93aW5nIHNjcmVlbnNob3Q6CgohW10oaW1nL3BhY2thZ2VzLXBhbmUucG5nKXt3aWR0aD0iOTAlIn0KCllvdSBzaG91bGQgc2VlIGluc3RhbGxlZCBzb21lIGZhbWlsaWFyIHRpZHl0ZXh0IHBhY2thZ2VzIGZyb20gb3VyIFtHZXR0aW5nIFN0YXJ0ZWQgV2Fsa3Rocm91Z2hdKGh0dHBzOi8vc2JrZWxsb2dnLmdpdGh1Yi5pby9lY2ktNTg5L3VuaXQtMC91bml0LTAtd2Fsa3Rocm91Z2guaHRtbCkgbGlrZSB7ZHBseXJ9IGFuZCB7cmVhZHJ9IHdoaWNoIHdlJ2xsIGJlIHVzaW5nIGFnYWluIHNob3J0bHkuIFlvdSBzaG91bGQgYWxzbyBzZWUgYW4gaW1wb3J0YW50IHBhY2thZ2UgY2FsbCB7aWdyYXBofSB0aGF0IHdlIHdpbGwgcmVseSBvbiBoZWF2aWx5IGZvciBvdXIgbmV0d29yayBhbmFseXNlcyBpbiB0aGlzIGNvdXJzZS4KCklmIHlvdSBhcmUgd29ya2luZyBpbiBSU3R1ZGlvIERlc2t0b3AsIG9yIG5vdGljZSB0aGF0IHRoZSBwYWNrYWdlcyBoYXZlIG5vdCBiZWVuIGluc3RhbGxlZCBhbmQvb3IgbG9hZGVkLCBydW4gdGhlIGZvbGxvd2luZyBgaW5zdGFsbC5wYWNrYWdlcygpYCBmdW5jdGlvbiBjb2RlIHRvIGluc3RhbGwgdGhlIHt0aWR5dmVyc2V9IGFuZCB7aWdyYXBofSBwYWNrYWdlczoKCmBgYHtyLCBldmFsPUZBTFNFfQppbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQppbnN0YWxsLnBhY2thZ2VzKCJpZ3JhcGgiKSAKYGBgCgpMZXQncyBnbyBhaGVhZCBhbmQgdXNlIHRoZSBgbGlicmFyeSgpYCBmdW5jdGlvbiBmb3IgdGhlIHt0aWR5dmVyc2V9IHBhY2thZ2UgYW5kIHJldmlldyB3aGljaCBwYWNrYWdlcyBmcm9tIHRoZSBbdGlkeXZlcnNlIGNvbGxlY3Rpb24gb2YgcGFja2FnZXNdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcpIHRoYXQgdGhpcyBwYWNrYWdlIGFsc28gbG9hZHMuCgpDbGljayB0aGUgZ3JlZW4gYXJyb3cgdG8gcnVuIHRoZSBmb2xsb3dpbmcgY29kZSBhbmQgbG9hZCBvdXIgcGFja2FnZXM6CgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyMjIyDwn46JIGlncmFwaCBQYWNrYWdlICoq8J+TpioqCgohW10oaW1nL2lncmFwaC5wbmcpe3dpZHRoPSIzMCUifQoKRm9yIG91ciBVbml0IDEgV2Fsa3Rocm91Z2gsIHdlIHdpbGwgcmVseSBoZWF2aWx5IG9uIHRoZSBbaWdyYXBoIG5ldHdvcmsgYW5hbHlzaXMgcGFja2FnZV0oaHR0cHM6Ly9pZ3JhcGgub3JnKS4gVGhlIG1haW4gZ29hbHMgb2YgdGhlIGlncmFwaCBwYWNrYWdlIGFuZCB0aGUgY29sbGVjdGlvbiBvZiBuZXR3b3JrIGFuYWx5c2lzIHRvb2xzIGl0IGNvbnRhaW5zIGFyZSB0byBwcm92aWRlIGEgc2V0IG9mIGRhdGEgdHlwZXMgYW5kIGZ1bmN0aW9ucyBmb3I6CgoxLiAgcGFpbi1mcmVlIGltcGxlbWVudGF0aW9uIG9mIGdyYXBoIGFsZ29yaXRobXMsCgoyLiAgZmFzdCBoYW5kbGluZyBvZiBsYXJnZSBncmFwaHMsIHdpdGggbWlsbGlvbnMgb2YgdmVydGljZXMgKGkuZS4sIGFjdG9ycyBvciBub2RlcykgYW5kIGVkZ2VzLAoKMy4gIGFsbG93aW5nIHJhcGlkIHByb3RvdHlwaW5nIHZpYSBoaWdoIGxldmVsIGxhbmd1YWdlcyBsaWtlIFIuCgpSdW4gdGhlIGNvZGUgY2h1bmsgYmVsb3cgdG8gbG9hZCB0aGUge2lncmFwaH0gbGlicmFyeToKCmBgYHtyfQpsaWJyYXJ5KGlncmFwaCkKYGBgCgojIyMgKirwn5GJIFlvdXIgVHVybioqICoq4qS1KioKClRha2UgYSBsb29rIGF0IHRoZSBtZXNzYWdlcyBmcm9tIHRoZSBvdXRwdXQgYWZ0ZXIgbG9hZGluZyB0aGUgaWdyYXBoIGxpYnJhcnkuIFdoYXQgdGlkeXZlcnNlIHBhY2thZ2VzIHNoYXJlIGlkZW50aWNhbGx5IG5hbWVkIGZ1bmN0aW9ucyB3aXRoIGlncmFwaD8KCldyaXRlIHlvdXIgcmVzcG9uc2UgaW4gdGhlIHNwYWNlIGJlbG93LgoKXC0KCiMjIyDwn6e2IEtuaXQgJiBDaGVjayDinIUKCkNvbmdyYXRzISBZb3UncmUgcmVhZHkgdG8gc3RhcnQgd3JhbmdsaW5nIHNvbWUgZGF0YSEgQmVmb3JlIHByb2NlZWRpbmcgZnVydGhlciwga25pdCB5b3VyIGRvY3VtZW50IGFuZCBjaGVjayB0byBzZWUgaWYgeW91IGVuY291bnRlciBhbnkgZXJyb3JzLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyAyLiBXUkFOR0xFCgpJbiBnZW5lcmFsLCBkYXRhIHdyYW5nbGluZyBpbnZvbHZlcyBzb21lIGNvbWJpbmF0aW9uIG9mIGNsZWFuaW5nLCByZXNoYXBpbmcsIHRyYW5zZm9ybWluZywgYW5kIG1lcmdpbmcgZGF0YSAoV2lja2hhbSAmIEdyb2xlbXVuZCwgMjAxNykuIFRoZSBpbXBvcnRhbmNlIG9mIGRhdGEgd3JhbmdsaW5nIGlzIGRpZmZpY3VsdCB0byBvdmVyc3RhdGUsIGFzIGl0IGludm9sdmVzIHRoZSBpbml0aWFsIHN0ZXBzIG9mIGdvaW5nIGZyb20gdGhlIHJhdyBkYXRhIHRvIGEgZGF0YXNldCB0aGF0IGNhbiBiZSBleHBsb3JlZCBhbmQgbW9kZWxlZCAoS3J1bW0gZXQgYWwsIDIwMTgpLgoKRm9yIG91ciBkYXRhIHdyYW5nbGluZyB0aGlzIHdlZWssIHdlJ3JlIGtlZXBpbmcgaXQgc2ltcGxlIHNpbmNlIHdvcmtpbmcgd2l0aCBuZXR3b3JrIGRhdGEgaXMgYSBiaXQgb2YgYSBkZXBhcnR1cmUgZnJvbSBvdXIgd29ya2luZyB3aXRoIHJlY3Rhbmd1bGFyIGRhdGEgZnJhbWVzLiBPdXIgcHJpbWFyeSBnb2FscyBmb3IgVW5pdCAxIGFyZSBsZWFybmluZyBob3cgdG86CgphLiAgKipJbXBvcnQgRGF0YSoqLiBBbiBvYnZpb3VzIGFuZCBhbHNvIGltcG9ydGFudCBmaXJzdCBzdGVwLCB3ZSBuZWVkIHRvICJyZWFkIiBvdXIgZGF0YSBpbnRvIFIgYW5kIGxlYXJuIGFib3V0IGZvcm1hdHRpbmcgZm9yIGVkZ2UtbGlzdHMgYW5kIG5vZGUgYXR0cmlidXRlIGZpbGVzLgoKYi4gICoqQ3JlYXRlIGEgTmV0d29yayBPYmplY3QqKi4gQmVmb3JlIHBlcmZvcm1pbmcgbmV0d29yayBhbmFseXNlcywgd2UnbGwgbmVlZCB0byBjb252ZXJ0IG91ciBkYXRhIGZyYW1lcyBpbnRvIHNwZWNpYWwgZGF0YSBmb3JtYXQgZm9yIHdvcmtpbmcgd2l0aCByZWxhdGlvbmFsIGRhdGEuCgpjLiAgKipTaW1wbGlmeSBOZXR3b3JrKiouIEZpbmFsbHksIHdlJ2xsIGxlYXJuIGFib3V0IGEgaGFuZHkgYHNpbXBsaWZ5KClgIGZ1bmN0aW9uIGluIHRoZSB7aWdyYXBofSBwYWNrYWdlIGZvciBjb2xsYXBzaW5nIG11bHRpcGxlIHRpZXMgYmV0d2VlbiBhY3RvcnMgYW5kIHJlbW92aW5nICJzZWxmLWxvb3BzLiIKCiMjIyAyYS4gSW1wb3J0IERhdGEKCiMjIyMgVGhlIEVkZ2UtTGlzdCBGb3JtYXQKClRvIGdldCBzdGFydGVkLCB3ZSBuZWVkIHRvIGltcG9ydCwgb3IgInJlYWQiLCBvdXIgZGF0YSBpbnRvIFIuIFRoZSBmdW5jdGlvbiB1c2VkIHRvIGltcG9ydCB5b3VyIGRhdGEgd2lsbCBkZXBlbmQgb24gdGhlIGZpbGUgZm9ybWF0IG9mIHRoZSBkYXRhIHlvdSBhcmUgdHJ5aW5nIHRvIGltcG9ydCwgYnV0IFIgaXMgcHJldHR5IGFkZXB0IGF0IHdvcmtpbmcgd2l0aCBtYW55IGZpbGVzIHR5cGVzLgoKVGFrZSBhIGxvb2sgaW4gdGhlIGAvZGF0YWAgZm9sZGVyIGluIHlvdXIgRmlsZXMgcGFuZS4gWW91IHNob3VsZCBzZWUgdGhlIGZvbGxvd2luZyAuY3N2IGZpbGVzOgoKLSAgIGBkbHQxLWVkZ2VsaXN0LmNzdmAKCi0gICBgZGx0MS1ub2Rlcy5jc3ZgCgpBcyBpdHMgbmFtZSBpbXBsaWVzLCB0aGUgZmlyc3QgZmlsZSBgZGx0MS1lZGdlbGlzdC5jc3ZgIGlzIGFuIGVkZ2UtbGlzdCB0aGF0IGNvbnRhaW5zIGluZm9ybWF0aW9uIGFib3V0IGVhY2ggdGllLCBvciByZWxhdGlvbiBiZXR3ZWVuIHR3byBhY3RvcnMgaW4gYSBuZXR3b3JrLiBJbiB0aGlzIGNvbnRleHQsIGEgInRpZSIgaXMgYSByZXBseSBieSBvbmUgcGFydGljaXBhbnQgaW4gdGhlIGRpc2N1c3Npb24gZm9ydW0gdG8gdGhlIHBvc3Qgb2YgYW5vdGhlciBwYXJ0aWNpcGFudCAtLSBvciBpbiBzb21lIGNhc2VzIHRvIHRoZWlyIG93biBwb3N0ISBUaGVzZSB0aWVzIGJldHdlZW4gYSBzaW5nbGUgYWN0b3IgYXJlIGNhbGxlZCAic2VsZi1sb29wcyIgYW5kIGFzIHdlJ2xsIHNlZSBsYXRlciBpbiB0aGlzIHNlY3Rpb24sIGlncmFwaCBoYXMgYSBzcGVjaWFsIGZ1bmN0aW9uIHRvIHJlbW92ZSB0aGVzZSBzZWxmIGxvb3BzIGZyb20gYSBzb2Npb2dyYW0sIG9yIG5ldHdvcmsgdmlzdWFsaXphdGlvbi4KClRoZSBlZGdlLWxpc3QgZm9ybWF0IGlzIHNsaWdodGx5IGRpZmZlcmVudCB0aGFuIG90aGVyIGZvcm1hdHMgeW91IGhhdmUgbGlrZWx5IHdvcmtlZCB3aXRoIGJlZm9yZSBpbiB0aGF0IHRoZSB2YWx1ZXMgaW4gdGhlIGZpcnN0IHR3byBjb2x1bW5zIGVhY2ggcm93IHJlcHJlc2VudCBhIGR5YWQsIG9yIHRpZSBiZXR3ZWVuIHR3byBub2RlcyBpbiBhIG5ldHdvcmsuIEFuIGVkZ2UtbGlzdCBjYW4gYWxzbyBjb250YWluIG90aGVyIGluZm9ybWF0aW9uIHJlZ2FyZGluZyB0aGUgc3RyZW5ndGgsIGR1cmF0aW9uLCBvciBmcmVxdWVuY3kgb2YgdGhlIHJlbGF0aW9uc2hpcCwgc29tZXRpbWUgY2FsbGVkICJ3ZWlnaHQiLCBpbiBhZGRpdGlvbiB0byBvdGhlciAiZWRnZSBhdHRyaWJ1dGVzLiIKCkluIGFkZGl0aW9uIHRvIG91ciBgU2VuZGVyYCBhbmQgYFJlY2lldmVyYCBkeWFkIHBhaXJzLCBvdXIgRExUIDEgZGF0YXNldCBjb250YWlucyB0aGUgZm9sbG93aW5nIGVkZ2UgYXR0cmlidXRlczoKCi0gICBgU2VuZGVyYCA9IFVuaXF1ZSBpZGVudGlmaWVyIG9mIGF1dGhvciBvZiBjb21tZW50CgotICAgYFJlY2VpdmVyYCA9IFVuaXF1ZSBpZGVudGlmaWVyIG9mIGlkZW50aWZpZWQgcmVjaXBpZW50IG9mIGNvbW1lbnQKCi0gICBgVGltZXN0YW1wYCA9IFRpbWUgcG9zdCBvciByZXBseSB3YXMgcG9zdGVkCgotICAgYFBhcmVudGAgPSBQcmltYXJ5IGNhdGVnb3J5IG9yIHRvcGljIG9mIHRocmVhZAoKLSAgIGBDYXRlZ29yeWAgPSBTdWJjYXRlZ29yeSBvciBzdWJ0b3BpYyBvZiB0aHJlYWQKCi0gICBgVGhyZWFkX2lkYCA9IFVuaXF1ZSBpZGVudGlmaWVyIG9mIGEgdGhyZWFkCgotICAgYENvbW1lbnRfaWRgID0gVW5pcXVlIGlkZW50aWZpZXIgb2YgYSBjb21tZW50XFwKCkxldCdzIHVzZSB0aGUgYHJlYWRfY3N2KClgIGZ1bmN0aW9uIGZyb20gdGhlIHtyZWFkcn0gcGFja2FnZSBpbnRyb2R1Y2VkIGluIHRoZSBHZXR0aW5nIFN0YXJ0ZWQgd2Fsa3Rocm91Z2ggdG8gcmVhZCBpbiBvdXIgZWRnZS1saXN0IGFuZCBwcmludCB0aGUgbmV3IGB0aWVzYCBkYXRhIGZyYW1lOgoKYGBge3J9CnRpZXMgPC0gcmVhZF9jc3YoImRhdGEvZGx0MS1lZGdlbGlzdC5jc3YiLCAKICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKFNlbmRlciA9IGNvbF9jaGFyYWN0ZXIoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWNlaXZlciA9IGNvbF9jaGFyYWN0ZXIoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQ2F0ZWdvcnkgVGV4dGAgPSBjb2xfc2tpcCgpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBDb21tZW50IElEYCA9IGNvbF9jaGFyYWN0ZXIoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgRGlzY3Vzc2lvbiBJRGAgPSBjb2xfY2hhcmFjdGVyKCkpKQoKdGllcwpgYGAKCk5vdGUgdGhlIGFkZGl0aW9uIG9mIHRoZSBgY29sX3R5cGVzID1gIGFyZ3VtZW50IGZvciBjaGFuZ2luZyB0aGUgY29sdW1uIHR5cGVzIHRvIGNoYXJhY3RlciBzdHJpbmdzIHNpbmNlIHRoZSBudW1iZXJzIGZvciB0aG9zZSBwYXJ0aWN1bGFyIGNvbHVtbnMgaW5kaWNhdGUgYWN0b3JzIChgU2VuZGVyYCBhbmQgYFJlY2lldmVyYCkgYW5kIGF0dHJpYnV0ZXMgKGBDb21tZW50X0lEYCBhbmQgYERpc2N1c3Npb25fSWRgKS4gV2UgYWxzbyBza2lwcGVkIHRoZSBgQ2F0ZWdvcnkgVGV4dGAgc2luY2UgdGhpcyB3YXMgbGVmdCBibGFuayBmb3IgZGVpZGVudGlmaWNhdGlvbiBwdXJwb3Nlcy4KCioqUlN0dWRpbyBUaXA6KiogSW1wb3J0aW5nIGRhdGEgYW5kIGRlYWxpbmcgd2l0aCBkYXRhIHR5cGVzIGNhbiBiZSBhIGJpdCB0cmlja3ksIGVzcGVjaWFsbHkgZm9yIGJlZ2lubmVycy4gRm9ydHVuYXRlbHksIFJTdHVkaW8gaGFzIGFuICJJbXBvcnQgRGF0YXNldCIgZmVhdHVyZSBpbiB0aGUgRW52aXJvbm1lbnQgUGFuZSB0aGF0IGNhbiBoZWxwIHlvdSB1c2UgdGhlIHtyZWFkcn0gcGFja2FnZSBhbmQgYXNzb2NpYXRlZCBmdW5jdGlvbnMgdG8gZ3JlYXRseSBmYWNpbGl0YXRlIHRoaXMgcHJvY2Vzcy4KCiFbXShpbWcvaW1wb3J0LWRhdGEucG5nKQoKIyMjICoq8J+RiSBZb3VyIFR1cm4qKiAqKuKktSoqCgpDb25zaWRlciB0aGUgZXhhbXBsZSBwaWN0dXJlZCBiZWxvdyBvZiBhIGRpc2N1c3Npb24gdGhyZWFkIGZyb20gdGhlIFBsYW5uaW5nIGZvciB0aGUgRGlnaXRhbCBMZWFybmluZyBUcmFuc2l0aW9uIGluIEstMTIgU2Nob29scyAoRExUIDEpIHdoZXJlIG91ciBkYXRhIG9yZ2luYXRlZC4gVGhpcyB0aHJlYWQgd2FzIGluaXRpYXRlZCBieSBwYXJ0aWNpcGFudCBJLCBzbyB0aGUgY29tbWVudHMgYnkgSiBhbmQgTiBhcmUgY29uc2lkZXJlZCB0byBiZSBkaXJlY3RlZCBhdCBJLiBUaGUgY29tbWVudCBvZiBCLCBob3dldmVyLCBpcyBhIGRpcmVjdCByZXNwb25zZSB0byB0aGUgY29tbWVudCBieSBOIGFzIHNpZ25hbGVkIGJ5IHRoZSB1c2Ugb2YgdGhlIHF1b3RlLWZlYXR1cmUgYXMgd2VsbCBhcyB0aGUgZXhwbGljaXQgbWVudGlvbmluZyBvZiBOJ3MgbmFtZSB3aXRoaW4gQidzIGNvbW1lbnQuCgohW10oaW1nL2Rpc2N1c3Npb24tdGhyZWFkLnBuZykKCk5vdyBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnMgYXMgdGhleSByZWxhdGUgdG8gdGhlIERMVCAxIGVkZ2UtbGlzdCB3ZSBqdXN0IHJlYWQgaW50byBSLgoKMS4gIFdoaWNoIGFjdG9ycyBpbiB0aGlzIHRocmVhZCBhcmUgdGhlIGBTZW5kZXJgIGFuZCB0aGUgYFJlY2lldmVyYD8gV2hpY2ggYWN0b3IgaXMgYm90aD8KCiAgICAtICAgCgoyLiAgSG93IG1hbnkgZHlhZHMgYXJlIGluIHRoaXMgdGhyZWFkPyBXaGljaCBwYWlycyBvZiBhY3RvcnMgYXJlIGR5YWRzPwoKICAgIC0gICAKCioqU2lkZWJhcjoqKiBVbmZvcnR1bmF0ZWx5LCB0aGVzZSB0eXBlcyBvZiBudWFuY2VzIGluIGRpc2N1c3Npb24gZm9ydW0gZGF0YSBhcyBpbGx1c3RyYXRlZCBieSB0aGlzIHNpbXBsZSBleGFtcGxlIGFyZSByYXJlbHkgY2FwdHVyZWQgdGhyb3VnaCBhdXRvbWF0ZWQgYXBwcm9hY2hlcyB0byBjb25zdHJ1Y3RpbmcgbmV0d29ya3MuIEZvcnR1bmF0ZWx5LCB0aGUgZGF0YXNldCB5b3UgYXJlIHdvcmtpbmcgd2l0aCB3YXMgY2FyZWZ1bGx5IHJldmlld2VkIHRvIHRyeSBhbmQgY2FwdHVyZSBtb3JlIGFjY3VyYXRlbHkgdGhlIGludGVuZGVkIHJlY2lwaWVudHMgb2YgZWFjaCByZXBseS4KCiMjIyMgTm9kZSBBdHRyaWJ1dGVzCgpUaGUgc2Vjb25kIGZpbGUgd2UnbGwgYmUgdXNpbmcgY29udGFpbnMgYWxsIHRoZSBub2RlcyBvciBhY3RvcnMgKGkuZS4sIHBhcnRpY2lwYW50cyB3aG8gcG9zdGVkIHRvIHRoZSBkaXNjdXNzaW9uIGZvcnVtKSBhcyB3ZWxsIGFzIHNvbWUgb2YgdGhlaXIgYXR0cmlidXRlcyBzdWNoIGFzIGdlbmRlciBhbmQgeWVhcnMgb2YgZXhwZXJpZW5jZSBpbiBlZHVjYXRpb24uCgpDYXJvbHluICgyMDEzKSBub3RlcyB0aGF0IG1vc3Qgc29jaWFsIG5ldHdvcmsgYW5hbHlzZXMgaW5jbHVkZSB2YXJpYWJsZXMgdGhhdCBkZXNjcmliZSBhdHRyaWJ1dGVzIG9mIGFjdG9ycywgb25lcyB0aGF0IGFyZSBlaXRoZXIgY2F0ZWdvcmljYWwgKGUuZy4sIHNleCwgcmFjZSwgZXRjLikgb3IgY29udGludW91cyBpbiBuYXR1cmUgKGUuZy4sIHRlc3Qgc2NvcmVzLCBudW1iZXIgb2YgdGltZXMgYWJzZW50LCBldGMuKS4gVGhlc2UgYXR0cmlidXRlcyB0aGF0IGNhbiBiZSBpbmNvcnBvcmF0ZWQgaW50byBhIG5ldHdvcmsgZ3JhcGggb3IgbW9kZWwsIG1ha2luZyBpdCBtb3JlIGluZm9ybWF0aXZlIGFuZCBjYW4gYWlkIGluIHRlc3Rpbmcgb3IgZ2VuZXJhdGluZyBoeXBvdGhlc2VzLgoKVGhlc2UgYXR0cmlidXRlIHZhcmlhYmxlcyBhcmUgdHlwaWNhbGx5IGluY2x1ZGVkIGluIGEgcmVjdGFuZ3VsYXIgYXJyYXksIG9yIGRhdGFmcmFtZSwgdGhhdCBtaW1pY3MgdGhlIGFjdG9yLWJ5LWF0dHJpYnV0ZSB0aGF0IGlzIHRoZSBkb21pbmFudCBjb252ZW50aW9uIGluIHNvY2lhbCBzY2llbmNlLCBpLmUuIHJvd3MgcmVwcmVzZW50IGNhc2VzLCBjb2x1bW5zIHJlcHJlc2VudCB2YXJpYWJsZXMsIGFuZCBjZWxscyBjb25zaXN0IG9mIHZhbHVlcyBvbiB0aG9zZSB2YXJpYWJsZXMuCgpBcyBhbiBhc2lkZSwgQ2Fyb2x5biBhbHNvIHJlZmVycyB0byB0aGlzIGhpc3RvcmljYWwgcHJlZmVyZW5jZSBieSByZXNlYXJjaGVycyBmb3IgImFjdG9yLWJ5LWF0dHJpYnV0ZSIgZGF0YSwgaW4gdGhlIGFic2VuY2Ugb2YgcmVsYXRpb25hbCBkYXRhIGluIHdoaWNoIHRoZSBhY3RvciBoYXMgYmVlbiByZW1vdmVkIHRoZWlyIHNvY2lhbCBjb250ZXh0LCBhcyB0aGUgInNvY2lvbG9naWNhbCBtZWF0Z3JpbmRlciIgaW4gYWN0aW9uLiBTcGVjaWZpY2FsbHksIHRoaXMgaGlzdG9yaWNhbCBhcHByb2FjaCBhc3N1bWVzIHRoYXQgdGhlIGFjdG9yIGRvZXMgbm90IGludGVyYWN0IHdpdGggYW55b25lIGVsc2UgaW4gdGhlIHN0dWR5IGFuZCB0aGF0IG91dGNvbWVzIGFyZSBzb2xlbHkgZGVwZW5kZW50IG9mIHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIGluZGl2aWR1YWwuCgpSZWdhcmRsZXNzLCBsZXQncyByZWFkIGluIG91ciBub2RlIGF0dHJpYnV0ZSBmaWxlIGFuZCB0YWtlIGEgbG9vayBhdCB0aGUgYGFjdG9yc2AgYW5kIHRoZWlyIGF0dHJpYnV0ZXMgaW5jbHVkZWQgaW4gb3VyIGRhdGFzZXQ6CgpgYGB7cn0KYWN0b3JzIDwtIHJlYWRfY3N2KCJkYXRhL2RsdDEtbm9kZXMuY3N2IiwgCiAgICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKFVJRCA9IGNvbF9jaGFyYWN0ZXIoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZhY2lsaXRhdG9yID0gY29sX2NoYXJhY3RlcigpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwZXJ0ID0gY29sX2NoYXJhY3RlcigpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdCA9IGNvbF9jaGFyYWN0ZXIoKSkpCmBgYAoKIyMjICoq8J+RiSBZb3VyIFR1cm4qKiAqKuKktSoqCgpVc2UgdGhlIGNvZGUgY2h1bmsgYmVsb3cgYW5kIGEgZnVuY3Rpb24gb2YgeW91ciBjaG9vc2luZyB0byB0YWtlIGEgbG9vayBhdCB0aGUgYGFjdG9yc2AgZGF0YSBmcmFtZToKCmBgYHtyfQoKYGBgCgpNYXRjaCB1cCB0aGUgYXR0cmlidXRlcyBpbmNsdWRlZCBpbiB0aGUgbm9kZSBmaWxlIHdpdGggdGhlIGZvbGxvd2luZyBjb2RlYm9vayBkZXNjcmlwdG9ycy4gVGhlIGZpcnN0IG9uZSBoYXMgYmVlbiBkb25lIGFzIGFuIGV4YW1wbGUuCgotICAgYEZhY2lsaXRhdG9yYCA9IElkZW50aWZpY2F0aW9uIG9mIGNvdXJzZSBmYWNpbGl0YXRvciAoMSAqKj0qKiBpbnN0cnVjdG9yKQotICAgRHVtbXkgdmFyaWFibGUgZm9yIHdoZXRoZXIgcGFydGljaXBhbnRzIGxpc3RlZCBuZXR3b3JraW5nL2NvbGxhYm9yYXRpb24gd2l0aCBvdGhlcnMgYXMgb25lIG9mIHRoZWlyIGNvdXJzZSBnb2FscyBvbiB0aGUgcmVnaXN0cmF0aW9uIGZvcm0KLSAgIElkZW50aWZpZXIgb2YgImV4cGVydCBwYW5lbGlzdHMiIGludml0ZWQgdG8gY291cnNlIHRvIHNoYXJlIGV4cGVyaWVuY2UgdGhyb3VnaCByZWNvcmRlZCBRJkEKLSAgIElkZW50aWZpY2F0aW9uIG9mIGNvdXJzZSBmYWNpbGl0YXRvciAoMSAqKj0qKiBpbnN0cnVjdG9yKQotICAgUHJvZmVzc2lvbmFsIHJvbGUgKGVnLCB0ZWFjaGVyLCBsaWJyYXJpYW4sIGFkbWluaXN0cmF0b3IpCi0gICBZZWFycyBvZiBleHBlcmllbmNlIGFzIGFuIGVkdWNhdG9yCi0gICBXb3JrcyB3aXRoIGVsZW1lbnRhcnksIG1pZGRsZSwgYW5kL29yIGhpZ2ggc2Nob29sIHN0dWRlbnRzCi0gICBJbml0aWFsIGFzc2lnbm1lbnQgb2YgZGlzY3Vzc2lvbiBncm91cAoKIyMjIDJiLiBDcmVhdGUgTmV0d29yayBPYmplY3QKCkJlZm9yZSB3ZSBjYW4gYmVnaW4gdXNpbmcgbWFueSBvZiB0aGUgZnVuY3Rpb25zIGZyb20gdGhlIHtpZ3JhcGh9IHBhY2thZ2UgZm9yIHN1bW1hcml6aW5nIGFuZCB2aXN1YWxpemluZyBvdXIgRExUIDEgbmV0d29yaywgd2UgZmlyc3QgbmVlZCB0byBjb252ZXJ0IHRoZSBkYXRhIGZyYW1lcyB0aGF0IHdlIGltcG9ydGVkIGludG8gYW4gaWdyYXBoIG5ldHdvcmsgb2JqZWN0LCBvciBhbiBpZ3JhcGggZ3JhcGguIPCfpLfigI3imYIKCiMjIyMgQ29udmVydCB0byBpZ3JhcGggR3JhcGgKClRvIGRvIHRoYXQsIHdlIHdpbGwgdXNlIHRoZSBgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKClgIGZ1bmN0aW9uLiBOb3RlIHRoYXQgSSBpbmNsdWRlZCB0aGUgYGV2YWw9RkFMU0VgIGFyZ3VtZW50IGluIHRoZSBjb2RlIGJsb2NrIGJlbG93IHRvIHByZXZlbnQgdGhpcyBjb2RlIGZyb20gcnVubmluZyB3aGVuIHdlIGtuaXQgb3VyIGZpbmFsIGRvY3VtZW50LiBPdGhlcndpc2UgaXQgd2lsbCBwcm9kdWNlIGFuIGVycm9yIHNpbmNlIHdlIGNhbid0IGluY2x1ZGUgaGVscCBkb2N1bWVudGF0aW9uIGluIG91ciBrbml0dGVkIEhUTUwgZmlsZS4KClJ1biB0aGUgZm9sbG93aW5nIGNvZGUgdG8gdGFrZSBhIGxvb2sgYXQgdGhlIGhlbHAgZG9jdW1lbnRhdGlvbiBmb3IgdGhpcyBmdW5jdGlvbjoKCmBgYHtyLCBldmFsPUZBTFNFfQo/Z3JhcGhfZnJvbV9kYXRhX2ZyYW1lCmBgYAoKWW91IHByb2JhYmx5IHNhdyB0aGF0IHRoaXMgcGFydGljdWxhciBmdW5jdGlvbiB0YWtlcyB0aGUgZm9sbG93aW5nIHRocmVlIGFyZ3VtZW50cywgdHdvIG9mIHdoaWNoIGFyZSBkYXRhIGZyYW1lczoKCi0gICAqKmQqKsKgZGVzY3JpYmVzIHRoZSBlZGdlcyBvZiB0aGUgbmV0d29yay4gVGhlIGZpcnN0IHR3byBjb2x1bW5zIGFyZSB0aGUgSURzIG9mIHRoZSBzb3VyY2UgYW5kIHRoZSB0YXJnZXQgbm9kZSBmb3IgZWFjaCBlZGdlLCBpbiBvdXIgY2FzZSB0aGUgYFNlbmRlcmAgYW5kIGBSZXZpZXZlcmAgb2YgYSBkaXNjdXNzaW9uIHBvc3QgLS0gdGhlIG9yZGVyIG1hdHRlcnMhIFRoZSBmb2xsb3dpbmcgY29sdW1ucyBhcmUgZWRnZSBhdHRyaWJ1dGVzIHN1Y2ggYXMgd2VpZ2h0LCB0eXBlLCBsYWJlbCwgb3IgYW55dGhpbmcgZWxzZS4KCi0gICAqKnZlcnRpY2VzKirCoHN0YXJ0cyB3aXRoIGEgY29sdW1uIG9mIG5vZGUgSURzIGFuZCBhbnkgZm9sbG93aW5nIGNvbHVtbnMgYXJlIGludGVycHJldGVkIGFzIG5vZGUgYXR0cmlidXRlcy4KCi0gICAqKmRpcmVjdGVkKiogZGV0ZXJtaW5lcyB3aGV0aGVyIG9yIG5vdCB0byBjcmVhdGUgYSBkaXJlY3RlZCBncmFwaC4KClJ1biB0aGUgZm9sbG93aW5nIGNvZGUgdG8gc3BlY2lmeSBvdXIgYHRpZXNgIGRhdGEgZnJhbWUgYXMgdGhlIGVkZ2VzIG9mIG91ciBuZXR3b3JrLCBvdXIgYGFjdG9yc2AgZGF0YSBmcmFtZSBmb3IgdGhlIHZlcnRpY2VzIG9mIG91ciBuZXR3b3JrIGFuZCB0aGVpciBhdHRyaWJ1dGVzLCBhbmQgaW5kaWNhdGUgdGhhdCB0aGlzIGlzIGluZGVlZCBhIGRpcmVjdGVkIG5ldHdvcmsuCgpgYGB7cn0KbmV0d29yayA8LSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoZCA9IHRpZXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNlcyA9IGFjdG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGVkID0gVCkgCgpuZXR3b3JrCmBgYAoKQ2Fyb2x5biAoMjAxMykgcmVtaW5kcyB1cyB0aGF0IG9uZSBvZiB0aGUgc2ltcGxlc3QgYW5kIG9mdGVuIGlnbm9yZWQgc3RydWN0dXJhbCBwcm9wZXJ0eSBvZiBhIHNvY2lhbCBuZXR3b3JrIGlzIGl0cyBzaXplIGFuZCBleHBsYWlucyB0aGF0OgoKPiAqKnNpemUqKiBpcyBzaW1wbHkgYSBtZWFzdXJlIG9mIHRoZSBudW1iZXIgb2Ygbm9kZXMgaW4gdGhlIG5ldHdvcmsuCgpIZSBub3RlcyB0aGF0IHRoZSBzaXplIG9mIGEgbmV0d29yayBwbGF5cyBhbiBpbXBvcnRhbnQgcm9sZSBpbiBkZXRlcm1pbmluZyB3aGF0IGhhcHBlbnMgaW4gdGhlIG5ldHdvcmsuIEZvciBleGFtcGxlLCBpbiBhIGNsYXNzcm9vbSBvZiAzMCBzdHVkZW50cywgaXQgaXMgbm90IGhhcmQgdG8gaW1hZ2luZSB0aGF0IHRoZSBwYXR0ZXJuIG9mIHdobyBjb21tdW5pY2F0ZXMgd2l0aCB3aG9tIHdpbGwgbG9vayBtdWNoIGRpZmZlcmVudCB0aGFuIGlmIHRoZSBuZXR3b3JrIGNvbnNpc3RlZCBvZiBodW5kcmVkcyBvciBldmVuIHRob3VzYW5kcyBvZiBzdHVkZW50cyBsaWtlIGluIGEgTU9PQy4KCiMjIyAqKvCfkYkgWW91ciBUdXJuKiogKiripLUqKgoKVGFrZSBhIGxvb2sgYXQgdGhlIHZlcnkgZmlyc3QgbGluZSBvZiB0aGUgb3V0cHV0IHdoaWNoIGNvbnRhaW5zIHNvbWUgYmFzaWMgaW5mb3JtYXRpb24gYWJvdXQgb3VyIG5ldHdvcmsgYW5kIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczoKCjEuICBIb3cgbWFueSBub2RlcyBhbmQgZWRnZXMgYXJlIGluIG91ciBuZXR3b3JrPyBJcyB0aGlzIGNvbnNpc3RlbnQgd2l0aCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBpbiBvdXIgZGF0YSBmcmFtZXM/ICoqSGludDoqKiBDaGVjayB0aGUgRW52aXJvbm1lbnQgcGFuZS4KCiAgICAtICAgCgoyLiAgVGhlICJEIiBhbmQgdGhlICJOIiBpbmRpY2F0ZSB0aGF0IHRoaXMgaXMgYSAqKkQqKmlyZWN0ZWQgbmV0d29yayBhbmQgaGFzIHRoZSAqKk4qKmFtZSB2ZXJ0ZXggYXR0cmlidXRlcyBzZXQuIFdoeSBkbyB0aGUgdHdvIHNwYWNlcyB0aGF0IGZvbGxvdyB0aGVzZSBsZXR0ZXJzIGhhdmUgZGFzaGVzPyAqKkhpbnQ6KiogY2hlY2sgdGhlIGhlbHAgZmlsZXMuCgogICAgLSAgIAoKMy4gIFdoaWNoIHZlcnRleCBhdHRyaWJ1dGUgZGlkIGlncmFwaCBpbnRlcnByZXQgYXMgbnVtZXJpYz8KCiAgICAtICAgCgojIyMjIFNpbXBsaWZ5IEdyYXBoCgpBcyB5b3Ugc2F3IGZyb20gdGhlIGBuZXR3b3JrYCBvdXRwdXQsIG91ciBkYXRhc2V0IGhhcyAyNTI5IGVkZ2VzIG9yIHRpZXMgYW5kIGp1c3QgYSBxdWljayBzY2FuIG9mIHRoZSBlZGdlcyBpbiB0aGUgbmV0d29yayBzaG93cyB0aGF0IGVkZ2VzIGxpa2UgMzU2IC1cPiA0NDQgb2NjdXIgYXQgbGVhc3QgbW9yZSB0aGFuIG9uY2UuIFNvIHdlIGtub3cgdGhhdCBwYXJ0aWNpcGFudCAzNTYgaGFzIHJlcGxpZWQgdG8gcGFydGljaXBhbnQgNDQ0IGF0IGxlYXN0IHR3aWNlLgoKRm9ydHVuYXRlbHksIHRoZSB7aWdyYXBofSBwYWNrYWdlIGhhcyBhIGBzaW1wbGlmeSgpYCBmdW5jdGlvbiBmb3IgY29sbGFwc2luZyBtdWx0aXBsZSBlZGdlcyBzbyB0aGV5IGFyZSBub3QgcmVwcmVzZW50ZWQgbW9yZSB0aGFuIG9uY2Ugd2hlbiB3ZSB3YW50IHZpc3VhbGx5IGRlcGljdCBvdXIgbmV0d29yayB3aXRoIGEgc29jaW9ncmFtLgoKTGV0J3MgdXNlIHRoYXQgZnVuY3Rpb24gdG8gc2ltcGxpZnkgb3VyIG5ldHdvcmsgYW5kIHNhdmUgaXQgYXMgYSBgc2ltcGxlX25ldHdvcmssYCBvciBhIHNpbXBsZSBncmFwaCwgd2hpY2ggY29udGFpbnMgbm8gc2VsZi1sb29wcyBvciBkdXBsaWNhdGUgZWRnZXMgYW5kIHdoaWNoIGJ5IGRlZmF1bHQgdGhlIGBzaW1wbGlmeSgpYCBmdW5jdGlvbiByZW1vdmVzOgoKYGBge3J9CnNpbXBsZV9uZXR3b3JrIDwtIHNpbXBsaWZ5KG5ldHdvcmssIHJlbW92ZS5sb29wcyA9IFRSVUUpIAoKc2ltcGxlX25ldHdvcmsKYGBgCgpOb3RlIHRoYXQgYHNpbXBsaWZ5KClgIHJlbW92ZXMgc2VsZi1sb29wcyBieSBkZWZhdWx0LCB0aGlzIGRvZXMgbm90IHJlYWxseSBuZWVkIHRvIGJlIGluY2x1ZGVkLiBJZiB5b3Ugd2FudGVkIHRvIGtlZXAgdGhlbSwgeW91IHdvdWxkIHNpbXBseSBzZXQgdGhpcyB0byBgRkFMU0VgLgoKIyMjICoq8J+RiSBZb3VyIFR1cm4qKiAqKuKktSoqCgpUYWtlIGEgbG9vayBhdCB0aGUgb3V0cHV0IGZvciBvdXIgc2ltcGxlIGdyYXBoIG5vdyBhbmQgYW5zd2VyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOgoKMS4gIEhvdyBtYW55IHVuaXF1ZSBlZGdlcyBhcmUgaW4gdGhlIG5ldHdvcms/IFdoeSBkbyB5b3UgdGhpbmsgdGhpcyBpcyBjb25zaWRlcmFibHkgbGVzcyB0aGFuIG91ciB0b3RhbCBlZGdlcz8KCiAgICAtICAgCgoyLiAgRGlkIHdlIHBvdGVudGlhbGx5IGxvc2UgYW55IGltcG9ydGFudCBvciB1c2VmdWwgaW5mb3JtYXRpb24gYnkgY29sbGFwc2luZyBtdWx0aXBsZSBlZGdlcyBpbnRvIGEgc2luZ2xlIGVkZ2Ugb3IgYnkgcmVtb3Zpbmcgc2VsZi1sb29wcz8KCiAgICAtICAgCgojIyMgQWRkIEVkZ2UgV2VpZ2h0cwoKV2Ugbm90ZWQgZWFybGllciB0aGF0IGVkZ2VzIGNhbiBhbHNvIGNvbnRhaW4gYXR0cmlidXRlcyBzdWNoIGFzIHN0cmVuZ3RoLCBkdXJhdGlvbiBvciBmcmVxdWVuY3ksIHNvbWV0aW1lIGNhbGxlZCAid2VpZ2h0LiIgVGhlc2Ugd2VpZ2h0cyBjYW4gbm90IG9ubHkgaGVscCB1cyBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdHdvIGFjdG9ycywgYnV0IGFsc28gYWlkIGluIHZpc3VhbGl6YXRpb24gYW5kIG1vZGVsaW5nIGxhdGVyIG9uLgoKV2hlbiB3ZSB1c2VkIHRoZSBgc2ltcGxpZnkoKWAgZnVuY3Rpb24gZWFybGllciwgaXQgY29sbGFwc2VkIG91ciBkdXBsaWNhdGUgZWRnZXMgYnV0IHdlIGxvc3Qgc29tZSB2aXRhbCBpbmZvcm1hdGlvbiBhcyBhIHJlc3VsdCwgbmFtZWx5IHRoZSBmcmVxdWVuY3kgb2YgcmVwbGllcyBhbW9uZyBwYWlycyBvZiBlZHVjYXRvcnMgaW4gb3VyIGRpc2N1c3Npb24gZm9ydW0uCgpGb3J0dW5hdGVseSwgdGhlIGBzaW1wbGlmeSgpYCBmdW5jdGlvbiBjb250YWlucyBhbiBhcmd1bWVudCB0aGF0IHdpbGwgYWxsb3cgdXMgdG8gY291bnQgdGhlIG51bWJlciBvZiB0aWVzIGJldHdlZW4gdHdvIGFjdG9ycywgc2ltaWxhciB0byBob3cgd2UgbWlnaHQgdXNlIHRoZSBgY291bnQoKWAgZnVuY3Rpb24gaW4gdGhlIHtkcGx5cn0gcGFja2FnZSBsaWtlIHNvOgoKYGBge3J9CmVkZ2Vfd2VpZ2h0cyA8LSBjb3VudCh0aWVzLCBTZW5kZXIsIFJlY2VpdmVyKQoKZWRnZV93ZWlnaHRzCmBgYAoKSW4gdGhpcyBjYXNlLCB3ZSBzZWUgdGhhdCBwYXJ0aWNpcGFudCAxIHJlcGxpZWQgdG8gcGFydGljaXBhbnQgMTQ0IHR3aWNlIHRocm91Z2hvdXQgdGhlIGNvdXJzZS4KClRvIGFkZCB3ZWlnaHRzIHRvIG91ciBzaW1wbGlmaWVkIG5ldHdvcmssIHdlIGZpcnN0IG5lZWQgdG8gYWRkIGEgYHdlaWdodGAgdmFyaWFibGUgdG8gdGhlIGVkZ2VzIGluIG91ciBvcmlnaW5hbCBgbmV0d29ya2AgaWdyYXBoIG9iamVjdC4KClRoZSB7aWdyYXBofSBwYWNrYWdlIGhhcyBhIHVuaXF1ZSBzeW50YXggZm9yIHdvcmtpbmcgd2l0aCBhdHRyaWJ1dGVzIG9mIG5ldHdvcmsgb2JqZWN0cy4gVG8gYWRkIGEgd2VpZ2h0IGF0dHJpYnV0ZSB0byB0aGUgYEUoKWAgZWRnZXMgaW4gb3VyIGBuZXR3b3JrYCB3ZSdsbCB1c2UgdGhlIGAkYCBvcGVyYXRvciB3aGljaCBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYSBuZXcgYHdlaWdodGAgdmFyaWFibGUgLS0gb3Igc2VsZWN0IGEgdmFyaWFibGUgYXMgd2UnbGwgc2VlIGxhdGVyIG9uIC0tIGFuZCB3ZSdsbCB1c2UgdGhlIGA8LWAgYXNzaWdubWVudCBvcGVyYXRvciB0byBhZGQgYW4gaW5pdGlhbCB2YWx1ZSBvZiBgMWAgZm9yIHRoZSB3ZWlnaHQgb2YgZWFjaCBlZGdlLgoKTGV0J3MgcHV0IHRoYXQgYWxsIHRvZ2V0aGVyIGFuZCBydW4gdGhlIGNvZGUgdG8gYWRkIGEgd2VpZ2h0IG9mIDEgdG8gZWFjaCBlZGdlIGluIG91ciBuZXR3b3JrCgpgYGB7cn0KRShuZXR3b3JrKSR3ZWlnaHQgPC0gMSAgCmBgYAoKTm93IGxldCdzIHRha2UgYSBsb29rIGF0IG91ciBpZ3JhcGggbmV0d29yayBvYmplY3QgYWdhaW46CgpgYGB7cn0KbmV0d29yawpgYGAKCldlIGNhbiBzZWUgdGhhdCBvdXIgbmV0d29yayBpcyBub3cgd2VpZ2h0ZWQgYXMgaW5kaWNhdGVkIGJ5IHRoZSAiVyIgYW5kIHRoYXQgb3VyIG5ldyBgd2VpZ2h0YCBhdHRyaWJ1dGUgaGFzIGJlZW4gYWRkZWQuCgpXZSBjYW4gbm93IHVzZSB0aGUgYGVkZ2UuYXR0ci5jb21iID1gIGFyZ3VtZW50IHRvICJzdW0iIHRoZSB3ZWlnaHRzIGZvciBlYWNoIG9jY3VycmVuY2Ugb2YgYSBwYWlyIG9mIGFjdG9ycywgc28gaWYgMSByZXBsaWVkIHRvIHBhcnRpY2lwYW50IDE0NCBmaXZlIHRpbWVzIG92ZXIgdGhlIGNvdXJzZSBvZiB0aGUgTU9PQy1FZCwgdGhlcmUgd291bGQgYmUgYSB3ZWlnaHQgb2YgNSBmb3IgdGhhdCBwYWlyLgoKUnVuIHRoZSBjb2RlIHRvIHNpbXBsaWZ5IG91ciB3ZWlnaHRlZCBuZXR3b3JrOgoKYGBge3J9CndlaWdodGVkX25ldHdvcmsgPC0gc2ltcGxpZnkobmV0d29yaywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGdlLmF0dHIuY29tYiA9IGxpc3Qod2VpZ2h0PSJzdW0iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKYGBgCgpMZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgb3V0cHV0IGFuZCBpZ25vcmUgdGhlIGVycm9yIG1lc3NhZ2UgZm9yIG5vdzoKCmBgYHtyLCBldmFsPUZBTFNFfQp3ZWlnaHRlZF9uZXR3b3JrCmBgYAoKIyMjICoq8J+RiSBZb3VyIFR1cm4qKiAqKuKktSoqCgpUYWtlIGEgbG9vayBhdCB0aGUgb3V0cHV0IGZvciBvdXIgc2ltcGxlIGdyYXBoIG5vdyBhbmQgYW5zd2VyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOgoKMS4gIEhvdyBkb2VzIHRoZSBudW1iZXIgb2YgdG90YWwgZWRnZXMgYW5kIHVuaXF1ZSBlZGdlcyB0aGlzIGNvbXBhcmUgdG8gdGhlIHRvdGFscyByZXBvcnRlZCBmb3IgdGhlIERMVCAyIGNvdXJzZSBpbiBvdXIgW2d1aWRpbmcgc3R1ZHldKGh0dHBzOi8vZ2l0aHViLmNvbS9zYmtlbGxvZ2cvZWNpLTU4OS9ibG9iL21haW4vdW5pdC0xL2xpdC9zbmFfbW9vY19pcnJvZGxfYmpldF9hcnRpY2xlcy5wZGYpPwoKICAgIC0gICAKCiMjIyDwn6e2IEtuaXQgJiBDaGVjayDinIUKCkNvbmdyYXRzISBZb3UgbWFkZSBpdCB0byB0aGUgZW5kIG9mIGRhdGEgd3JhbmdsaW5nIHNlY3Rpb24gYW5kIGFyZSByZWFkeSB0byBzdGFydCBhbmFseXNpcyEgQmVmb3JlIHByb2NlZWRpbmcgZnVydGhlciwga25pdCB5b3VyIGRvY3VtZW50IGFuZCBjaGVjayB0byBzZWUgaWYgeW91IGVuY291bnRlciBhbnkgZXJyb3JzLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyAzLiBFWFBMT1JFCgpBcyBub3RlZCBpbiB0aGUgR2V0dGluZyBTdGFydGVkIFdhbGt0aHJvdWdoLCBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIGludm9sdmVzIHRoZSBwcm9jZXNzZXMgb2YgZGVzY3JpYmluZyB5b3VyIGRhdGEgKHN1Y2ggYXMgYnkgY2FsY3VsYXRpbmcgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIG9mIG51bWVyaWMgdmFyaWFibGVzLCBvciBjb3VudGluZyB0aGUgZnJlcXVlbmN5IG9mIGNhdGVnb3JpY2FsIHZhcmlhYmxlcykgYW5kLCBvZnRlbiwgdmlzdWFsaXppbmcgeW91ciBkYXRhIHByaW9yIHRvIG1vZGVsaW5nLgoKSW4gU2VjdGlvbiAzLCB3ZSB3aWxsIGxlYXJuIHNvbWUgbmV3IGZ1bmN0aW9ucyBmb3IgcmV0cmlldmluZyBiYXNpYyBuZXR3b3JrIGRlc2NyaXB0aXZlcyByZWxhdGVkIHRvIG91ciByZXNlYXJjaCBxdWVzdGlvbiBhbmQgY3JlYXRlIGEgbmV0d29yayB2aXN1YWxpemF0aW9uIHRvIGhlbHAgaWxsdXN0cmF0ZSBrZXkgZmluZGluZ3MuIFNwZWNpZmljYWxseSwgaW4gdGhpcyBzZWN0aW9uIHdlJ2xsIGxlYXJuIHRvOgoKYS4gICoqRXhhbWluZSBCYXNpYyBEZXNjcmlwdGl2ZXMqKi4gV2UgZm9jdXMgcHJpbWFyaWx5IG9uIGFjdG9ycyBhbmQgZWRnZXMgaW4gdGhpcyB3YWxrdGhyb3VnaCwgaW5jbHVkaW5nIHRoZSBlZGdlcyB3aWdodHMgd2UgYWRkZWQgaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24gYXMgd2VsbCBhcyBub2RlIGRlZ3JlZSwgYW5kIGltcG9ydCBhbmQgZmFpcmx5IGludHVpdGl2ZSBtZWFzdXJlIG9mIGNlbnRyYWxpdHkuCgpiLiAgKipNYWtlIGEgU29jaW9ncmFtKiouIEZpbmFsbHksIHdlIHdyYXAgdXAgdGhlIGV4cGxvcmUgcGhhc2VzIGJ5IGxlYXJuaW5nIHRvIHBsb3QgYSBuZXR3b3JrIGFuZCB0d2VhayBrZXkgZWxlbWVudHMgbGlrZSB0aGUgc2l6ZSwgc2hhcGUsIGFuZCBwb3NpdGlvbiBvZiBub2RlcyBhbmQgZWRnZXMgdG8gYmV0dGVyIGF0IGNvbW11bmljYXRpbmcga2V5IGZpbmRpbmdzLgoKIyMjIDNhLiBFeGFtaW5lIEJhc2ljIERlc2NyaXB0aXZlcwoKTWFueSBhbmFseXNlcyBvZiBzb2NpYWwgbmV0d29ya3MgYXJlIHByaW1hcmlseSBkZXNjcmlwdGl2ZS4gQXMgQ2Fyb2x5biAoMjAxMykgbm90ZXMgdGhhdCB0aGVzZSBkZXNjcmlwdGl2ZSBzdHVkaWVzIGFpbSBlaXRoZXIgdG8gcmVwcmVzZW50IHRoZSBuZXR3b3JrJ3MgdW5kZXJseWluZyBzb2NpYWwgc3RydWN0dXJlIHRocm91Z2ggZGF0YS1yZWR1Y3Rpb24gdGVjaG5pcXVlcyBvciB0byBjaGFyYWN0ZXJpemUgbmV0d29yayBwcm9wZXJ0aWVzIHRocm91Z2ggbmV0d29yayBtZWFzdXJlcy4KCiMjIyMgTm9kZSBEZWdyZWUKCkEga2V5IHN0cnVjdHVyYWwgcHJvcGVydHkgb2YgbmV0d29ya3MgaXMgdGhlIGNvbmNlcHQgb2YgY2VudHJhbGl6YXRpb24uIEEgbmV0d29yayB0aGF0IGlzIGhpZ2hseSBjZW50cmFsaXplZCBpcyBvbmUgaW4gd2hpY2ggcmVsYXRpb25zIGFyZSBmb2N1c2VkIG9uIGEgc21hbGwgbnVtYmVyIG9mIGFjdG9ycyBvciBldmVuIGEgc2luZ2xlIGFjdG9yIGluIGEgbmV0d29yaywgd2hlcmVhcyB0aWVzIGluIGEgZGVjZW50cmFsaXplZCBuZXR3b3JrIGFyZSBkaWZmdXNlIGFuZCBzcHJlYWQgb3ZlciBhIG51bWJlciBvZiBhY3RvcnMuIE9uZSBvZiB0aGUgbW9zdCBjb21tb24gZGVzY3JpcHRpdmVzIHJlcG9ydGVkIGluIG5ldHdvcmsgc3R1ZGllcyBhbmQgYSBwcmltYXJ5IG1lYXN1cmUgb2YgY2VudHJhbGl6YXRpb24gaXMgKipkZWdyZWUqKi4KCj4gRGVncmVlIGlzIHRoZSBudW1iZXIgb2YgdGllcyB0byBhbmQgZnJvbSBhbiBlZ28uIEluIGEgZGlyZWN0ZWQgbmV0d29yaywgaW4tZGVncmVlIGlzIHRoZSBudW1iZXIgb2YgdGllcyByZWNlaXZlZCwgd2hlcmVhcyBvdXQtZGVncmVlIGlzIHRoZSBudW1iZXIgb2YgdGllcyBzZW50LgoKVGhlIHtpZ3JhcGh9IHBhY2thZ2UgaGFzIGFuIGFwdGx5IG5hbWVkIGZ1bmN0aW9uIGBkZWdyZWUoKWAgZm9yIHJldHJpZXZpbmcgZGVncmVlLCBpbi1kZWdyZWUsIGFuZCBvdXQtZGVncmVlIGZvciBhbGwgYWN0b3JzIGluIGEgbmV0d29yay4KClJ1biB0aGUgZm9sbG93aW5nIGNvZGUgdG8gZXh0cmFjdCBtZWFzdXJlcyBhbmQgc2F2ZSB0byBgbm9kZV9kZWdyZWVgIHdoaWNoIHdlJ2xsIGV4YW1pbmUgaW4ganVzdCBhIGJpdDoKCmBgYHtyfQpub2RlX2RlZ3JlZSA8LSBkZWdyZWUod2VpZ2h0ZWRfbmV0d29yaywgbW9kZSA9ICJhbGwiKQpgYGAKCioqTm90ZSoqLiBXZSBzZXQgdGhlIGBtb2RlID1gIGFyZ3VtZW50IGluIHRoaXMgZnVuY3Rpb24gdG8gImFsbCIgd2hpY2ggZ2l2ZSB1cyB0aGUgdG90YWwgbnVtYmVyIG9mIHBhcnRpY2lwYW50cyB0aGF0IGVhY2ggYWN0b3IgaW4gb3VyIG5ldHdvcmsgd2l0aCBzZW50IG9yIHJlY2VpdmVkIGEgcmVwbHkuCgpMZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGBub2RlX2RlZ3JlZWAgaW4gb3VyIG5ldHdvcmsgYnkgdXNpbmcgUidzIGJ1aWx0IGluIGBoaXN0KClgIGZ1bmN0aW9uIGZvciBjcmVhdGluZyBoaXN0b2dyYW1zLiBJIHNldCB0aGUgdmFsdWUgb2YgYGJyZWFrcyA9YCwgb3IgYmlucyBpbiBvdXIgaGlzdG9ncmFtLCB0byAzMCBzaW5jZSBJIGFscmVhZHkga25vdyBzb21lIGFjdG9ycyBpbiB0aGlzIG5ldHdvcmsgaGF2ZSBhIHZlcnkgaGlnaCBkZWdyZWUuCgpgYGB7cn0KaGlzdChub2RlX2RlZ3JlZSwgYnJlYWtzID0gMzApCmBgYAoKV2UgY2FuIHNlZSB0aGF0IG1vc3QgYWN0b3JzIGluIHRoZSBuZXR3b3JrIGFyZSBjb25uZWN0ZWQgdG8gdmVyeSBmZXcgaW5kaXZpZHVhbHMgd2hpbGUgYSBjb3VwbGUgYWN0b3JzIGluIHRoaXMgbmV0d29yayBhcmUgY29ubmVjdGVkIHRvIGEgdmVyeSBsYXJnZXIgbnVtYmVyLCBuZWFybHkgMjAwIGFuZCAzNTAgcmVzcGVjdGl2ZWx5IQoKTm93IGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBtZWFuIGFuZCBtZWRpYW4gZm9yIGBub2RlX2RlZ3JlZWAgdXNpbmcgc29tZSBvdGhlciB7YmFzZX0gUiBmdW5jdGlvbnM6CgpgYGB7cn0KbWVhbihub2RlX2RlZ3JlZSkKbWVkaWFuKG5vZGVfZGVncmVlKQpgYGAKCldlIHNlZSB0aGF0IHRoZSBtZWFuIHN1Z2dlc3RzIHRoZSBwYXJ0aWNpcGFudHMgYXJlLCBvbiBhdmVyYWdlLCBjb25uZWN0ZWQgdG8gYWJvdXQgOCBvdGhlciBwYXJ0aWNpcGFudHMgaW4gdGhlIE1PT0MtRWQsIGJ1dCB0aGlzIGlzIGxpa2VseSBoZWF2aWx5IHNrZXdlZCBieSB0aGUgdHdvIGluZGl2aWR1YWxzIHdpdGggYSBkaXNwcm9wb3J0aW9uYXRlIG51bWJlciBvZiBjb25uZWN0aW9ucy4gVGhlIG1lZGlhbiBpcyBwcm9iYWJseSBhIGJldHRlciBjaGFyYWN0ZXJpemF0aW9uIG9mIHRoZSB0eXBpY2FsIG51bWJlciBvZiBlZHVjYXRvcnMgYSBwYXJ0aWNpcGFudCBoYXMgc2VudCBvciByZWNlaXZlZCBhIHJlcGx5LgoKIyMjIyMgSW4tRGVncmVlCgpMZXQncyBnbyBhaGVhZCBhbmQgdGFrZSBhIGxvb2sgYXQgaW4tZGVncmVlIG5leHQ6CgpgYGB7cn0KaW5fZGVncmVlIDwtIGRlZ3JlZSh3ZWlnaHRlZF9uZXR3b3JrLCBtb2RlPSJpbiIpCgpoaXN0KGluX2RlZ3JlZSwgYnJlYWtzID0gMzApCm1lYW4oaW5fZGVncmVlKQptZWRpYW4oaW5fZGVncmVlKQpgYGAKCkFnYWluLCBtb3N0IHBhcnRpY2lwYW50cyByZWNlaXZlZCBhIHJlcGx5IGZyb20gc21hbGwgbnVtYmVyIG9mIGluZGl2aWR1YWxzLgoKIyMjICoq8J+RiSBZb3VyIFR1cm4qKiAqKuKktSoqCgpVc2UgdGhlIGNvZGUgY2h1bmsgYmVsb3cgdG8gZXhhbWluZSB0aGUgZGlzdHJpYnV0aW9uLCBtZWFuIGFuZCBtZWRpYW4gb2YgYG91dF9kZWdyZWVgOgoKYGBge3J9CgpgYGAKCkluIHRoZSBzcGFjZSBiZWxvdywgd3JpdGUgeW91ciBpbnRlcnByZXRhdGlvbiBvZiB0aGVzZSByZXN1bHRzLgoKXC0KCiMjIyMgRWRnZSBXZWlnaHRzCgpGaW5hbGx5LCBsZXQncyBhbHNvIHRha2UgYSBsb29rIGF0IHRoZSBkaXN0cmlidXRpb24sIG1lYW4gYW5kIG1lZGlhbiBvZiB0aGUgZWRnZSB3ZWlnaHRzIHdlIGFkZGVkIHRvIG91ciBncmFwaC4KClJlY2FsbCBmcm9tIGVhcmxpZXIgdGhhdCB0aGUge2lncmFwaH0gcGFja2FnZSBoYXMgYSB1bmlxdWUgc3ludGF4IGZvciBhY2Nlc3Npbmcgbm9kZSBhbmQgZWRnZSBhdHRyaWJ1dGVzLiBGb3IgZWRnZXMgd2UgdXNlIGBFKClgIGFuZCBpbmNsdWRlZCB0aGUgbmFtZSBvZiB0aGUgbmV0d29yayBvYmplY3Qgd2Ugd2FudCB0byB1c2UsIGZvbGxvd2VkIGJ5IHRoZSBgJGAgb3BlcmF0b3IgdG8gc2VsZWN0IHRoZSBhdHRyaWJ1dGUuCgpgYGB7cn0Kd2VpZ2h0cyA8LSBFKHdlaWdodGVkX25ldHdvcmspJHdlaWdodAoKaGlzdCh3ZWlnaHRzLCBicmVha3MgPSAxMCkKbWVhbih3ZWlnaHRzKQptZWRpYW4od2VpZ2h0cykKCmBgYAoKSXQgbG9va3MgbGlrZSB0aGUgdmFzdCBtYWpvcml0eSBvciBwYXJ0aWNpcGFudHMgZWl0aGVyIHNlbnQgb3IgcmVjZWl2ZWQgYSByZXBseSBmcm9tIGp1c3Qgb25lIG90aGVyIHBhcnRpY2lwYW50LgoKIyMjICoq8J+RiSBZb3VyIFR1cm4qKiAqKuKktSoqCgpUaGUgdXNlIG9mIHRoZSBgJGAgaXMgYWN0dWFsbHkgc3RhbmRhcmQgYWNyb3NzIFIgYW5kIGEgdmVyeSB1c2VmdWwgb3BlcmF0b3IuCgpVc2UgdGhlIGNvZGUgY2h1bmsgYmVsb3cgdG8gY3JlYXRlIGEgaGlzdG9ncmFtIGFuZCBjYWxjdWxhdGUgdGhlIG1lYW4gYW5kIG1lZGlhbiBmcm9tIHRoZSBlZGdlIHdlaWdocyBjcmVhdGVkIGVhcmxpZXIgaW4gdGhlIFtBZGQgRWRnZSBXZWlnaHRzXSBzZWN0aW9uIGJ5IHVzaW5nIHRoZSBgZWRnZV93ZWlnaHRzYCBkYXRhIGZyYW1lLCB0aGUgYCRgIG9wZXJhdG9yLCBhbmQgY29sdW1uIGBuYCB3aGljaCBjb250YWlucyB0aGUgY291bnRzIGZvciBlYWNoIHVuaXF1ZSBlZGdlLgoKYGBge3J9CgpgYGAKCkFyZSB0aGVzZSByZXN1bHRzIGNvbnNpc3RlbnQgd2l0aCBvdXIgc3VtbWFyeSBvZiBlZGdlIHdlaWdodHMgd2UgY3JlYXRlZCBhYm92ZT8KClwtCgojIyAzYi4gTWFrZSBhIFNvY2lvZ3JhbQoKSWYgeW91IHJlY2FsbCBmcm9tIG91ciBbMWEuIFJldmlldyB0aGUgUmVzZWFyY2hdIHNlY3Rpb24sIG9uZSBvZiB0aGUgZGVmaW5pbmcgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBzb2NpYWwgbmV0d29yayBwZXJzcGVjdGl2ZSBpcyBpdHMgdXNlIG9mIGdyYXBoaWMgaW1hZ2VyeSB0byByZXByZXNlbnQgYWN0b3JzIGFuZCB0aGVpciByZWxhdGlvbnMgd2l0aCBvbmUgYW5vdGhlci4gVG8gZW1waGFzaXplIHRoaXMgcG9pbnQsIENhcm9seW4gKDIwMTMpIHJlcG9ydGVkIHRoYXQ6Cgo+IFRoZSB2aXN1YWxpemF0aW9uIG9mIHNvY2lhbCBuZXR3b3JrcyBoYXMgYmVlbiBhIGNvcmUgcHJhY3RpY2Ugc2luY2UgaXRzIGZvdW5kYXRpb24gbW9yZSB0aGFuIDkwIHllYXJzIGFnbyBhbmQgcmVtYWlucyBhIGhhbGxtYXJrIG9mIGNvbnRlbXBvcmFyeSBzb2NpYWwgbmV0d29yayBhbmFseXNpcy7CoAoKTmV0d29yayB2aXN1YWxpemF0aW9uIGNhbiBiZSB1c2VkIGZvciBhIHZhcmlldHkgb2YgcHVycG9zZXMsIHJhbmdpbmcgZnJvbSBoaWdobGlnaHRpbmcga2V5IGFjdG9ycyB0byBldmVuIHNlcnZpbmcgYXMgd29ya3Mgb2YgYXJ0LiBUaGlzIGV4Y2VsbGVudCBmaWd1cmUgZnJvbSBLYXR5YSBPZ255YW5vdmEncyBhbHNvIGV4Y2VsbGVudCB0dXRvcmlhbCBvbiBbU3RhdGljIGFuZCBEeW5hbWljIE5ldHdvcmsgVmlzdWFsaXphdGlvbiB3aXRoIFJdKGh0dHBzOi8va2F0ZXRvLm5ldC9uZXR3b3JrLXZpc3VhbGl6YXRpb24vKSBoZWxwcyBpbGx1c3RyYXRlIHRoZSB2YXJpZXR5IG9mIGdvYWxzIGEgZ29vZCBuZXR3b3JrIHZpc3VhbGl6YXRpb24gY2FuIGFjY29tcGxpc2g6CgohW10oaW1nL3Zpei1nb2Fscy5qcGVnKXt3aWR0aD0iODAlIn0KClRoZXNlIHZpc3VhbCByZXByZXNlbnRhdGlvbnMgb2YgdGhlIGFjdG9ycyBhbmQgdGhlaXIgcmVsYXRpb25zLCBpLmUuIHRoZSBuZXR3b3JrLCBhcmUgY2FsbGVkIGEgc29jaW9ncmFtLiBBY3RvcnMgd2hvIGFyZSBtb3N0IGNlbnRyYWwgdG8gdGhlIG5ldHdvcmssIHN1Y2ggYXMgdGhvc2Ugd2l0aCBoaWdoZXIgbm9kZSBkZWdyZWVzLCBhcmUgdXN1YWxseSBwbGFjZWQgaW4gdGhlIGNlbnRlciBvZiB0aGUgc29jaW9ncmFtIGFuZCB0aGVpciB0aWVzIGFyZSBwbGFjZWQgbmVhciB0aGVtLiBBcyB3ZSdsbCBzZWUgaW4ganVzdCBhIGJpdCwgdGhvc2UgdHdvIGFjdG9ycyB3aXRoIGh1bmRyZWRzIG9mIHRpZXMgd2lsbCBiZSBwbGFjZWQgYnkgbW9zdCBncmFwaCBsYXlvdXQgYWxnb3JpdGhtcyBpbiB0aGUgY2VudGVyIG9mIHRoZSBncmFwaC4KCkZvciBVbml0IDEsIHdlJ2xsIGJlIHVzaW5nIHRoZSBgcGxvdCgpYCBmdW5jdGlvbiBmcm9tIFIncyBidWlsdCBpbiB7Z3JhcGhpY3N9IHBhY2thZ2UgdG8gbWFrZSBhIHNvY2lvZ3JhbS4KCkxldCdzIHJ1biB0aGUgY29kZSBhbmQgc2VlIHdoYXQgd2UgZ2V0IHdpdGhvdXQgYW55IHR3ZWFraW5nIGFuZCBzZWUgd2hhdCB0aGUgcGxvdCBmdW5jdGlvbiBwcm9kdWNlczoKCmBgYHtyfQpwbG90KHdlaWdodGVkX25ldHdvcmspCgpgYGAKCklmIHRoaXMgaGFkIGJlZW4gYSBzbWFsbGVyIG5ldHdvcmsgbGlrZSBvbmUgZ2VuZXJhdGVkIGZyb20gYSB0ZWFjaGVyIHByb2Zlc3Npb25hbCBkZXZlbG9wbWVudCB3b3Jrc2hvcCwgdGhpcyBtaWdodCBoYXZlIGJlZW4gdXNlZnVsLCBidXQgZm9yIGxhcmdlIG5ldHdvcmtzIGxpa2Ugb3VyIE1PT0MtRWQgZGlzY3Vzc2lvbiBmb3J1bXMsIHRoaXMgZG9lc24ndCBjb21tdW5pY2F0ZSBtdWNoLiBJbiBmYWN0LCBpdCdzIHZpc3VhbGl6YXRpb25zIGxpa2UgdGhlc2UgdGhhdCBnaXZlIHNvY2lvZ3JhbXMgdGhlIHVuZmxhdHRlcmluZyBuaWNrbmFtZSBvZiAiaGFpciBiYWxsIiBwbG90cy4KCkZvcnR1bmF0ZWx5LCB0aGUge2lncmFwaH0gcGFja2FnZSBpbmNsdWRlcyBhIFtwbGV0aG9yYSBvZiBwbG90dGluZyBwYXJhbWV0ZXJzXShodHRwczovL2lncmFwaC5vcmcvci9kb2MvcGxvdC5jb21tb24uaHRtbCkgZm9yIGltcHJvdmluZyB0aGUgbGF5b3V0IGFuZCB2aXN1YWwgZGVzaWduIG9mIG5ldHdvcmsgZ3JhcGhzIQoKVGhlcmUgYXJlIG1hbnkgd2F5cyB0byBtb2RpZnkgdmVydGljZXMgYW5kIGVkZ2VzIGluIGEgc29jaW9ncmFtIHRvIGltcHJvdmUgcmVhZGFiaWxpdHkuIFVwIHRvIGZvdXIgYXR0cmlidXRlcyBvZiBlYWNoIGFjdG9yIGNhbiBiZSBsYXllcmVkIG9udG8gdGhlIHNvY2lvZ3JhbSBieSBhbHRlcmluZyB0aGUgY29sb3IsIHNoYXBlLCBsYWJlbCwgYW5kIHNpemUgb2YgdGhlIHN5bWJvbC4gQW5kIGF0dHJpYnV0ZXMgZm9yIGVkZ2VzIGNhbiBiZSByZXByZXNlbnRlZCBpbiBhIHJhbmdlIG9mIHdheXMgYXMgd2VsbC4KCiMjIyBSZW1vdmUgTGFiZWxzCgpPbmUgcXVpY2sgZml4IGlzIHRvIHNpbXBseSByZW1vdmUgdGhlIGxhYmVscyBieSBhZGRpbmcgdGhlIGB2ZXJ0ZXgubGFiZWwgPWAgYXJndW1lbnQgYW5kIHNldHRpbmcgaXQgdG8gYE5BYC4KClNpbmNlIHRoZSBudW1iZXIgbGFiZWxzIGRvbid0IHByb3ZpZGUgbXVjaCB1c2VmdWwgaW5mb3JtYXRpb24sIGxldCdzIGdvIGFoZWFkIGFuZCByZW1vdmUgdGhlbToKCmBgYHtyfQpwbG90KHdlaWdodGVkX25ldHdvcmssCiAgICAgdmVydGV4LmxhYmVsID0gTkEpCmBgYAoKV2UgY2FuIG5vdyBhdCBsZWFzdCBzZWUgdGhlIG5vZGVzLCBvciB2ZXJ0aWNlcywgYnV0IHdpdGggNDQ1IHBhcnRpY2lwYW50cyBpbiB0aGUgZm9ydW1zLCBtYW55IGFyZSBtYXNrZWQgYnkgdGhlIGRlZmF1bHQgc2l6ZSBvZiBlYWNoIG5vZGUuCgojIyMgQ2hhbmdlIHZlcnRleCBzaXplCgpCeSBkZWZhdWx0LCB0aGUgc2l6ZSBvZiBub2RlcyBpcyAxNS4gTGV0J3MgYWRkIHRoZSBgdmVydGV4LnNpemUgPWAgYXJndW1lbnQgYW5kIGNoYW5nZSB0aGF0IHRvIDE6CgpgYGB7cn0KcGxvdCh3ZWlnaHRlZF9uZXR3b3JrLAogICAgIHZlcnRleC5sYWJlbCA9IE5BLAogICAgIHZlcnRleC5zaXplID0gMSkKYGBgCgpBIGxpdHRsZSBiZXR0ZXIsIGJ1dCBsZXQncyB1c2UgdGhlIGBub2RlX2RlZ3JlZWAgd2UgY2FsY3VsYXRlZCB0byBlbXBoYXNpemUgdGhvc2Ugd2lodCBncmVhdGVyIGNvbm5lY3Rpb25zIGluIHRoZSBjb3Vyc2UgYnkgc3Vic3RpdHV0ZSBgbm9kZV9kZWdyZWVgIGZvciBhIHNwZWNpZmljIHZhbHVlLgoKYGBge3J9CnBsb3Qod2VpZ2h0ZWRfbmV0d29yaywKICAgICB2ZXJ0ZXgubGFiZWwgPSBOQSwKICAgICB2ZXJ0ZXguc2l6ZSA9IG5vZGVfZGVncmVlKQpgYGAKCldob29wcyEgVGhpcyBjZXJ0YWlubHkgZW1waGFzaXplcyB0aGUgZGlzcHJvcG9ydGlvbmF0ZSBudW1iZXIgb2YgdGllcyBhbW9uZyB0aGVzZSB0d28gcGFydGljaXBhbnRzLCBidXQgbm90IHF1aXRlIHdoYXQgd2UncmUgZ29pbmcgZm9yLgoKU2luY2UgYG5vZGVfZGVncmVlYCBpcyBqdXN0IGEgbGlzdCBvZiB2YWx1ZXMgZm9yIGVhY2ggbm9kZSB3ZSBjYW4gdHJlYXQgaXQgbGlrZSBhIG51bWJlci4gTGV0J3MgZGl2aWRlIHRoYXQgYnkgMTAgdG8gcmVkdWNlIHRoZSByZWxhdGl2ZSBzaXplOgoKYGBge3J9CnBsb3Qod2VpZ2h0ZWRfbmV0d29yaywKICAgICB2ZXJ0ZXgubGFiZWwgPSBOQSwKICAgICB2ZXJ0ZXguc2l6ZSA9IG5vZGVfZGVncmVlLzEwKQpgYGAKClRoYXQncyBiZXR0ZXIsIGFuZCBoZWxwcyBoaWdobGlnaHQgb3VyIHR3byBtYWluIGFjdG9ycyB3aXRob3V0IG92ZXJzaGFkb3dpbmcgdGhlIHJlc3QsIGJ1dCB0aG9zZSBhcnJvd3MgYXJlIGRlZmluaXRlbHkgYW4gZXllc29yZS4KCiMjIyBSZWR1Y2UgYXJyb3cgc2l6ZQoKTGV0J3MgYWRkIHRoZSBgZWRnZS5hcnJvdy5zaXplID1gIGFyZ3VtZW50IGFuZCBkcmFtYXRpY2FsbHkgcmVkdWNlOgoKYGBge3J9CnBsb3Qod2VpZ2h0ZWRfbmV0d29yaywKICAgICB2ZXJ0ZXgubGFiZWwgPSBOQSwKICAgICB2ZXJ0ZXguc2l6ZSA9IG5vZGVfZGVncmVlKi4xLAogICAgIGVkZ2UuYXJyb3cuc2l6ZSA9IC4wNCkKYGBgCgpNdWNoIGJldHRlciwgbm93IGxldCdzIGRlYWwgd2l0aCB0aGUgc2l6ZSBvZiB0aGUgZWRnZXMuCgojIyMjIEFkanVzdCBFZGdlIFdpZHRoCgpXZSBjYW4gYWRkIHRoZSBgZWRnZS53aWR0aCA9YCBhcmd1bWVudCB0byBoZWxwIG1pbmltaXplIGVkZ2Ugb3ZlcmxhcCB5ZXQgc3RpbGwgbWFrZSB0aGVtIHZpc2libGUuIFRoaXMgaXMgYSBiaXQgb2YgdHJpYWwgYW5kIGVycm9yIGJ1dCBsZXQncyBnaXZlIC4yIGEgdHJ5IHNpbmNlIHRoZSBkZWZhdWx0IGlzIDE6CgpgYGB7cn0KcGxvdCh3ZWlnaHRlZF9uZXR3b3JrLAogICAgIHZlcnRleC5sYWJlbCA9IE5BLAogICAgIHZlcnRleC5zaXplID0gbm9kZV9kZWdyZWUqLjA1LAogICAgIGVkZ2UuYXJyb3cuc2l6ZSA9IC4wNCwKICAgICBlZGdlLndpZHRoID0gLjIpCmBgYAoKTm90ZSB0aGF0IHdlIGNvdWxkIGFsc28gc2V0IGBlZGdlLndpdGggPWAgdG8gdGhlIHdlaWdodCBvZiBlYWNoIGVkZ2UsIHNpbWlsYXIgdG8gaG93IHdlIHVzZWQgZGVncmVlIGZvciB0aGUgc2l6ZSBvZiBlYWNoIG5vZGUuCgpMZXQncyBnaXZlIHRoYXQgYSB0cnk6CgpgYGB7cn0KcGxvdCh3ZWlnaHRlZF9uZXR3b3JrLAogICAgIHZlcnRleC5sYWJlbCA9IE5BLAogICAgIHZlcnRleC5zaXplID0gbm9kZV9kZWdyZWUqLjEsCiAgICAgZWRnZS5hcnJvdy5zaXplID0gLjA0LAogICAgIGVkZ2Uud2lkdGggPSBFKHdlaWdodGVkX25ldHdvcmspJHdlaWdodCkKYGBgCgpOb3QgbXVjaCBvZiBhbiBpbXByb3ZlbWVudCwgaWYgYXQgYWxsLCBnaXZlbiBob3cgbWFueSBlZGdlcyBhcmUgaW4gb3VyIG5ldHdvcmsuCgpMZXQncyB0cnkgZGl2aWRpbmcgdGhhdCB3ZWlnaHQgYnkgNSBzaW1pbGFyIHRvIHJlZHVjZSBsaWtlIHdpdGggZGlkIHdpdGggdGhlIGB2ZXJ0ZXguc2l6ZSA9YCBhcmd1bWVudDoKCmBgYHtyfQpwbG90KHdlaWdodGVkX25ldHdvcmssCiAgICAgdmVydGV4LmxhYmVsID0gTkEsCiAgICAgdmVydGV4LnNpemUgPSBub2RlX2RlZ3JlZSouMDUsCiAgICAgZWRnZS5hcnJvdy5zaXplID0gLjA1LAogICAgIGVkZ2Uud2lkdGggPSBFKHdlaWdodGVkX25ldHdvcmspJHdlaWdodC81KQpgYGAKCkJldHRlciwgYnV0IHNpbmNlIHdlIGtub3cgbW9zdCBlZGdlcyBoYXZlIGEgd2VpZ2h0IG9mIDEgdGhlcmUgcmVhbGx5IGlzbid0IHRvbyBtdWNoIHRvIHdvcmsgd2l0aCBoZXJlLgoKTGV0J3MgbW92ZSBvbiB0byBjaGFuZ2luZyBncmFwaCBsYXlvdXQhCgojIyMjIENoYW5nZSBMYXlvdXQKCk9uZSBvZiB0aGUgbWFqb3IgYWR2YW5jZXMgaW4gdmlzdWFsaXphdGlvbiBzaW5jZSB0aGUgZmlyc3QgaGFuZC1kcmF3biBzb2Npb2dyYW1zIGRldmVsb3BlZCBieSBKYWNvYiBNb3Jlbm8gKDE5MzQpIHRvIHJlcHJlc2VudCByZWxhdGlvbnMgYW1vbmcgY2hpbGRyZW4gaW4gc2Nob29sIGlzIHRoZSB1c2Ugb2Ygc29mdHdhcmUgYW5kIGFsZ29yaXRobXMgdG8gYXV0b21hdGljYWxseSBsYXlvdXQgbmV0d29ya3Mgb24gYSBncmlkLgoKVGhlcmUgYXJlIG1heSBkaWZmZXJlbnQgW2xheW91dCBtZXRob2RzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HcmFwaF9kcmF3aW5nI0xheW91dF9tZXRob2RzKSwgYnV0IHdlJ2xsIHN0YXJ0IHdpdGggdGhlIEZydWNodGVybWFuLVJlaW5nb2xkIChGUikgbGF5b3V0LCB3aGljaCBpcyBvbmUgb2YgdGhlIG1vc3QgdXNlZCBsYXlvdXQgYWxnb3JpdGhtcyBmb3IgbmV0d29yayB2aXN1YWxpemF0aW9uLiBUaGVzZSB0eXBlcyBvZiBmb3JjZS1kaXJlY3RlZCBhbGdvcml0aG1zIGdlbmVyYWxseSB3b3JrIHdlbGwgd2l0aCBsYXJnZSBuZXR3b3JrcyBhbmQgdHJ5IHRvIGxheW91dCBncmFwaHMgaW4gImFuIGFlc3RoZXRpY2FsbHktcGxlYXNpbmcgd2F5IiBieSBtYWtpbmcgZWRnZXMgcm91Z2hseSBlcXVhbCBpbiBsZW5ndGggYW5kIG1pbmltaXppbmcgb3ZlcmxhcC4KCkxldCBnaXZlIHRoZSBGUiBsYXlvdXQgYSB0cnkgYnkgdXNpbmcgdGhlIGBsYXlvdXQgPWAgYXJndW1lbnQgYW5kIHNwZWNpZnlpbmcgYGxheW91dF93aXRoX2ZyYDoKCmBgYHtyfQpwbG90KHdlaWdodGVkX25ldHdvcmssCiAgICAgdmVydGV4LmxhYmVsID0gTkEsCiAgICAgdmVydGV4LnNpemUgPSBub2RlX2RlZ3JlZSouMDUsCiAgICAgZWRnZS5hcnJvdy5zaXplID0gLjA1LAogICAgIGVkZ2Uud2lkdGggPSBFKHdlaWdodGVkX25ldHdvcmspJHdlaWdodC81LAogICAgIGxheW91dCA9IGxheW91dF93aXRoX2ZyKQpgYGAKCkJ5IGRlZmF1bHQsIHtpZ3JhcGh9IHVzZXMgYGxheW91dF9uaWNlbHlgLCBhIHNtYXJ0IGZ1bmN0aW9uIHRoYXQgY2hvb3NlcyBhIGxheW91dCBiYXNlZCBvbiB0aGUgZ3JhcGguIEdpdmVuIHRoZSBzaW1pbGFyaXR5IHdpdGggb3VyIHByZXZpb3VzIGdyYXBoLCBJJ20gYXNzdW1pbmcgaXQgY2hvc2UgdGhlIHRoZSBGUiBsYXlvdXQgYXMgd2VsbC4KCkxldCdzIHRyeSBvbmUgbW9yZSBqdXN0IGZvciBmdW46CgpgYGB7cn0KCnBsb3Qod2VpZ2h0ZWRfbmV0d29yaywKICAgICB2ZXJ0ZXgubGFiZWwgPSBOQSwKICAgICB2ZXJ0ZXguc2l6ZSA9IG5vZGVfZGVncmVlKi4wNSwKICAgICBlZGdlLmFycm93LnNpemUgPSAuMDUsCiAgICAgZWRnZS53aWR0aCA9IEUod2VpZ2h0ZWRfbmV0d29yaykkd2VpZ2h0LzUsCiAgICAgbGF5b3V0ID0gbGF5b3V0X2luX2NpcmNsZSkKCmBgYAoKSW50ZXJlc3RpbmcgYnV0IG5vdCB0ZXJyaWJseSB1c2VmdWwhCgpUaGVyZSBhcmUgbWFueSBvdGhlciBbaWdyYXBoIGxheW91dCBmdW5jdGlvbnNdKGh0dHBzOi8vaWdyYXBoLm9yZy9yL2RvYy9sYXlvdXRfLmh0bWwpLCBzb21lIG1vcmUgdXNlZnVsIHRoYW4gb3RoZXJzIGRlcGVuZGluZyBvbiB0aGUgY29udGV4dC4gV2UndmUgb25seSBzY3JhdGNoZWQgdGhlIHN1cmZhY2Ugb2Ygd2hhdCdzIHBvc3NpYmxlIHdpdGggbmV0d29yayBwbG90dGluZyBidXQgaG9wZWZ1bGx5IHRoaXMgaGF2ZSBnaXZlbiB5b3UgYSBzZW5zZSBvZiB3aGF0IHJlcXVpcmVkIHRvIGF2b2lkIHRoZSBkcmVhZGVkICJoYWlyIGJhbGwiIHBsb3QgYW5kIGNyZWF0ZSBhIG5ldHdvcmsgdml6IHRoYXQgY29tbXVuaWNhdGVzIHNvbWV0aGluZyB1c2VmdWwuCgojIyMgKirwn5GJIFlvdXIgVHVybioqICoq4qS1KioKClRyeSBtb2RpZnlpbmcgdGhlIGNvZGUgYmVsb3cgYnkgdHdlYWtpbmcgdGhlIGluY2x1ZGVkIGFyZ3VtZW50cy9wYXJhbWV0ZXJzIG9yIGFkZGluZyBuZXcgYXJndW1lbnRzL3BhcmFtZXRlcnMgdG8gbWFrZSBvdXIgcGxvdCBlaXRoZXIgbW9yZSAiYWVzdGhldGljYWxseSBwbGVhc2luZyIgb3IgbW9yZSBwdXJwb3NlZnVsIGluIHdoYXQgaXQncyB0cnlpbmcgdG8gY29tbXVuaWNhdGUuCgpZb3UncmUgYWxzbyB3ZWxjb21lIHRvIHRyeSBvdXQgc29tZSBvZiB0aGUgb3RoZXIgZ3JhcGhpbmcgb3B0aW9ucyBmcm9tIGZyb20gS2F0eWEgT2dueWFub3ZhJ3MgdHV0b3JpYWwgb24gW1N0YXRpYyBhbmQgRHluYW1pYyBOZXR3b3JrIFZpc3VhbGl6YXRpb24gd2l0aCBSXShodHRwczovL2thdGV0by5uZXQvbmV0d29yay12aXN1YWxpemF0aW9uLykuCgpUaGVyZSBhcmUgbm8gcmlnaHQgb3Igd3JvbmcgYW5zd2VycywganVzdCBoYXZlIHNvbWUgZnVuIHRyeWluZyBvdXQgZGlmZmVyZW50IGFwcHJvYWNoZXMhCgpgYGB7cn0KcGxvdCh3ZWlnaHRlZF9uZXR3b3JrLAogICAgIHZlcnRleC5sYWJlbCA9IE5BLAogICAgIHZlcnRleC5zaXplID0gbm9kZV9kZWdyZWUqLjA1LAogICAgIGVkZ2UuYXJyb3cuc2l6ZSA9IC4wNSwKICAgICBlZGdlLndpZHRoID0gRSh3ZWlnaHRlZF9uZXR3b3JrKSR3ZWlnaHQvNSwKICAgICBsYXlvdXQgPSBsYXlvdXRfd2l0aF9mcikKYGBgCgojIyMg8J+ntiBLbml0ICYgQ2hlY2sg4pyFCgpDb25ncmF0cyEgWW91IG1hZGUgaXQgdG8gdGhlIGVuZCBvZiB0aGUgRXhwbG9yZSBzZWN0aW9uIGFuZCBhcmUgcmVhZHkgdG8gbGVhcm4gYSBsaXR0bGUgYWJvdXQgbmV0d29yayBtb2RlbGluZyEgQmVmb3JlIHByb2NlZWRpbmcgZnVydGhlciwga25pdCB5b3VyIGRvY3VtZW50IGFuZCBjaGVjayB0byBzZWUgaWYgeW91IGVuY291bnRlciBhbnkgZXJyb3JzLgoKIyMgNC4gTU9ERUwKCkFzIGhpZ2hsaWdodGVkIGluwqBbQ2hhcHRlciAzIG9mIERhdGEgU2NpZW5jZSBpbiBFZHVjYXRpb24gVXNpbmcgUl0oaHR0cHM6Ly9kYXRhc2NpZW5jZWluZWR1Y2F0aW9uLmNvbS9jMDMuaHRtbCksIHRoZcKgKipNb2RlbCoqwqBzdGVwIG9mIHRoZSBkYXRhIHNjaWVuY2UgcHJvY2VzcyBlbnRhaWxzICJ1c2luZyBzdGF0aXN0aWNhbCBtb2RlbHMsIGZyb20gc2ltcGxlIHRvIGNvbXBsZXgsIHRvIHVuZGVyc3RhbmQgdHJlbmRzIGFuZCBwYXR0ZXJucyBpbiB0aGUgZGF0YS4iIFRoZSBhdXRob3JzIG5vdGUgdGhhdCB3aGlsZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGFuZCBkYXRhIHZpc3VhbGl6YXRpb24gZHVyaW5nIHRoZcKgKipFeHBsb3JlKiogc3RlcCBjYW4gaGVscCB1cyB0byBpZGVudGlmeSBwYXR0ZXJucyBhbmQgcmVsYXRpb25zaGlwcyBpbiBvdXIgZGF0YSwgc3RhdGlzdGljYWwgbW9kZWxzIGNhbiBiZSB1c2VkIHRvIGhlbHAgdXMgZGV0ZXJtaW5lIGlmIHJlbGF0aW9uc2hpcHMsIHBhdHRlcm5zIGFuZCB0cmVuZHMgYXJlIGFjdHVhbGx5IG1lYW5pbmdmdWwuCgpXZSB3aWxsIG5vdCBleHBsb3JlIHRoZSB1c2Ugb2YgbW9kZWxzIGZvciBTTkEgdW50aWwgVW5pdCAzLCBidXQgcmVjYWxsIGZyb20gW0EgU29jaWFsIE5ldHdvcmsgUGVyc3BlY3RpdmUgaW4gTU9PQy1FZHNdIHdhcyBndWlkZWQgYnkgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6CgoxLiAgV2hhdCBhcmUgdGhlIHBhdHRlcm5zIG9mIHBlZXIgaW50ZXJhY3Rpb24gYW5kIHRoZSBzdHJ1Y3R1cmUgb2YgcGVlciBuZXR3b3JrcyB0aGF0IGVtZXJnZSBvdmVyIHRoZSBjb3Vyc2Ugb2YgYSBNT09DLUVkPwoKMi4gIFRvIHdoYXQgZXh0ZW50IGRvIHBhcnRpY2lwYW50IGFuZCBuZXR3b3JrIGF0dHJpYnV0ZXMgKGUuZy4sIGhvbW9waGlseSwgcmVjaXByb2NpdHksIHRyYW5zaXRpdml0eSkgYWNjb3VudCBmb3IgdGhlIHN0cnVjdHVyZSBvZiB0aGVzZSBuZXR3b3Jrcz8KCjMuICBUbyB3aGF0IGV4dGVudCBkbyB0aGVzZSBuZXR3b3JrcyByZXN1bHQgaW4gdGhlIGNvLWNvbnN0cnVjdGlvbiBvZiBuZXcga25vd2xlZGdlPwoKVG8gYWRkcmVzcyBRdWVzdGlvbiAxLCBhY3RvcnMgaW4gdGhlIG5ldHdvcmsgd2VyZSBjYXRlZ29yaXplZCBpbnRvIGRpc3RpbmN0IG11dHVhbGx5IGV4Y2x1c2l2ZSBncm91cHMgdXNpbmcgdGhlIGNvcmUtcGVyaXBoZXJ5IGFuZCByZWd1bGFyIGVxdWl2YWxlbmNlIGZ1bmN0aW9ucyBvZiBVQ0lORVQuIFRoZSBmb3JtZXIgdXNlZCB0aGUgQ09SUiBhbGdvcml0aG0gdG8gZGl2aWRlIHRoZSBuZXR3b3JrIGludG8gYWN0b3JzIHRoYXQgYXJlIHBhcnQgb2YgYSBkZW5zZWx5IGNvbm5lY3RlZCBzdWJncm91cCwgb3IgImNvcmUiLCBmcm9tIHRob3NlIHRoYXQgYXJlIHBhcnQgb2YgdGhlIHNwYXJzZWx5IGNvbm5lY3RlZCBwZXJpcGhlcnkuIFJlZ3VsYXIgZXF1aXZhbGVuY2UgZW1wbG95cyB0aGUgUkVHRSBibG9ja21vZGVsaW5nIGFsZ29yaXRobSB0byBwYXJ0aXRpb24sIG9yIGdyb3VwLCBhY3RvcnMgaW4gdGhlIG5ldHdvcmsgYmFzZWQgb24gdGhlIHNpbWlsYXJpdHkgb2YgdGhlaXIgdGllcyB0byBvdGhlcnMgd2l0aCBzaW1pbGFyIHRpZXMuIEluIGVzc2VuY2UsIGJsb2NrbW9kZWxpbmcgcHJvdmlkZXMgYSBzeXN0ZW1hdGljIHdheSBmb3IgY2F0ZWdvcml6aW5nIGVkdWNhdG9ycyBiYXNlZCBvbiB0aGUgd2F5cyBpbiB3aGljaCB0aGV5IGludGVyYWN0ZWQgd2l0aCBwZWVycy4KCkFzIHdlIHNhdyB1cG9uIGp1c3QgYSBiYXNpYyB2aXN1YWwgaW5zcGVjdGlvbiBvZiBvdXIgbmV0d29yayBkdXJpbmcgdGhlIEV4cGxvcmUgc2VjdGlvbiwgdGhlcmUgd2FzIGEgc21hbGwgY29yZSBvZiBoaWdobHkgY29ubmVjdGVkIHBhcnRpY2lwYW50cyBzdXJyb3VuZGVkIGJ5IHRob3NlIG9uIHRoZSAicGVyaXBoZXJ5LCIgb3IgZWRnZSwgb2YgdGhlIG5ldHdvcmsgd2l0aCB2ZXJ5IGZldyBjb25uZWN0aW9ucy4gSW4gdGhlIERMVCAyIGNvdXJzZSwgdGhvc2Ugb24gdGhlIHBlcmlwaGVyeSBtYWRlIHVwIHJvdWdobHkgOTAlIG9mIG5ldHdvcmshIFRoZSBzdHVkeSBhbHNvIGZvdW5kIHJlbGF0aXZlbHkgaGlnaCBsZXZlbHMgb2YgcmVjaXByb2NhdGlvbiwgYnV0IGFsc28gZm91bmQgdGhhdCByb3VnaGx5IGEgcXVhcnRlciBvZiBwYXJ0aWNpcGFudHMgd2VyZSBjaGFyYWN0ZXJpemVkIGFzICJicm9kY2FzdGVycyIgLS0gZWR1Y2F0b3JzIHdobyBpbml0aWF0ZWQgYSBkaXNjdXNzaW9uIHRocmVhZCwgYnV0IG5laXRoZXIgcmVjaXByb2NhdGVkIHdpdGggdGhvc2Ugd2hvIHJlcGxpZWQsIG5vciBwb3N0ZWQgdG8gdGhyZWFkcyBpbml0aWF0ZWQgYnkgb3RoZXJzLgoKVG8gYWRkcmVzcyBRdWVzdGlvbiAyLCB0aGlzIHN0dWR5IHVzZSB0aGUgZXhwb25lbnRpYWwgZmFtaWx5IG9mIHJhbmRvbSBncmFwaCBtb2RlbHMgKEVSR007IGFsc28ga25vd24gYXMgcFwqIG1vZGVscyksIHdoaWNoIHByb3ZpZGUgYSBzdGF0aXN0aWNhbCBhcHByb2FjaCB0byBuZXR3b3JrIG1vZGVsaW5nIHRoYXQgYWRkcmVzc2VzIHRoZSBjb21wbGV4IGRlcGVuZGVuY2llcyB3aXRoaW4gbmV0d29ya3MuIEVSR01zIHByZWRpY3QgbmV0d29yayB0aWVzIGFuZCBkZXRlcm1pbmUgdGhlIHN0YXRpc3RpY2FsIGxpa2VsaWhvb2Qgb2YgYSBnaXZlbiBuZXR3b3JrIHN0cnVjdHVyZSwgYmFzZWQgb24gYW4gYXNzdW1lZCBkZXBlbmRlbmN5IHN0cnVjdHVyZSwgdGhlIGF0dHJpYnV0ZXMgb2YgdGhlIGluZGl2aWR1YWxzIChlLmcuLCBnZW5kZXIsIHBvcHVsYXJpdHksIGxvY2F0aW9uLCBwcmV2aW91cyB0aWVzKSBhbmQgcHJpb3Igc3RhdGVzIG9mIHRoZSBuZXR3b3JrLgoKIyMjICoq8J+RiSBZb3VyIFR1cm4qKiAqKuKktSoqCgpSZWNhbGwgZnJvbSB0aGUgWzFhLiBSZXZpZXcgdGhlIFJlc2VhcmNoXSB0aGF0IHlvdSB3ZXJlIGFza2VkIHRvIGlkZW50aWZ5IHR3byAibm9kZSBhdHRyaWJ1dGVzIiBmcm9tIHRoZSBkYXRhc2V0IHRoYXQgbWlnaHQgYmUgdXNlZnVsIGZvciBwcmVkaWN0aW5nIHBhcnRpY2lwYW50cyB3aG8gbWF5IGJlIG1vcmUgZW5nYWdlZCBvciBjZW50cmFsIHRvIHRoZSBuZXR3b3JrLgoKVGFrZSBsb29rIGF0IHBhZ2UgMjc2IG9mIFtBIHNvY2lhbCBuZXR3b3JrIHBlcnNwZWN0aXZlIG9uIHBlZXIgc3VwcG9ydGVkIGxlYXJuaW5nIGluIE1PT0NzIGZvciBlZHVjYXRvcnNdKGh0dHBzOi8vZ2l0aHViLmNvbS9zYmtlbGxvZ2cvZWNpLTU4OS9ibG9iL21haW4vdW5pdC0xL2xpdC9zbmFfbW9vY19pcnJvZGxfYmpldF9hcnRpY2xlcy5wZGYpLiBXZXJlIHlvdXIgcHJlZGljdGlvbnMgY29ycmVjdD8KClwtCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDUuIENPTU1VTklDQVRFCgpUaGUgZmluYWwgc3RlcCBpbiBvdXIgd29ya2Zsb3cvcHJvY2VzcyBpcyBzaGFyaW5nIHRoZSByZXN1bHRzIG9mIGFuYWx5c2lzIHdpdGggd2lkZXIgYSBhdWRpZW5jZS4gS3J1bW0gZXQgYWwuwqAoMjAxOCkgaGF2ZSBvdXRsaW5lIHRoZSBmb2xsb3dpbmcgMy1zdGVwIHByb2Nlc3MgZm9yIGNvbW11bmljYXRpbmcgd2l0aCBlZHVjYXRpb24gc3Rha2Vob2xkZXJzIHdoYXQgeW91IGhhdmUgbGVhcm5lZCB0aHJvdWdoIGFuYWx5c2lzOgoKMS4gICoqU2VsZWN0KiouIENvbW11bmljYXRpbmcgd2hhdCBvbmUgaGFzIGxlYXJuZWQgaW52b2x2ZXMgc2VsZWN0aW5nIGFtb25nIHRob3NlIGFuYWx5c2VzIHRoYXQgYXJlIG1vc3QgaW1wb3J0YW50IGFuZCBtb3N0IHVzZWZ1bCB0byBhbiBpbnRlbmRlZCBhdWRpZW5jZSwgYXMgd2VsbCBhcyBzZWxlY3RpbmcgYSBmb3JtIGZvciBkaXNwbGF5aW5nIHRoYXQgaW5mb3JtYXRpb24sIHN1Y2ggYXMgYSBncmFwaCBvciB0YWJsZSBpbiBzdGF0aWMgb3IgaW50ZXJhY3RpdmUgZm9ybSwgaS5lLsKgYSAiZGF0YSBwcm9kdWN0LiIKCjIuICAqKlBvbGlzaCoqLiBBZnRlciBjcmVhdGluZyBpbml0aWFsIHZlcnNpb25zIG9mIGRhdGEgcHJvZHVjdHMsIHJlc2VhcmNoIHRlYW1zIG9mdGVuIHNwZW5kIHRpbWUgcmVmaW5pbmcgb3IgcG9saXNoaW5nIHRoZW0sIGJ5IGFkZGluZyBvciBlZGl0aW5nIHRpdGxlcywgbGFiZWxzLCBhbmQgbm90YXRpb25zIGFuZCBieSB3b3JraW5nIHdpdGggY29sb3JzIGFuZCBzaGFwZXMgdG8gaGlnaGxpZ2h0IGtleSBwb2ludHMuCgozLiAgKipOYXJyYXRlKiouIFdyaXRpbmcgYSBuYXJyYXRpdmUgdG8gYWNjb21wYW55IHRoZSBkYXRhIHByb2R1Y3RzIGludm9sdmVzLCBhdCBhIG1pbmltdW0sIHBhaXJpbmcgYSBkYXRhIHByb2R1Y3Qgd2l0aCBpdHMgcmVsYXRlZCByZXNlYXJjaCBxdWVzdGlvbiwgZGVzY3JpYmluZyBob3cgYmVzdCB0byBpbnRlcnByZXQgdGhlIGRhdGEgcHJvZHVjdCwgYW5kIGV4cGxhaW5pbmcgdGhlIHdheXMgaW4gd2hpY2ggdGhlIGRhdGEgcHJvZHVjdCBoZWxwcyBhbnN3ZXIgdGhlIHJlc2VhcmNoIHF1ZXN0aW9uLgoKRm9yIHlvdXIgSW5kZXBlbmRlbnQgQW5hbHlzaXMgYXNzaWdubWVudCBmb3IgVW5pdCAxIG5leHQgd2VlaywgeW91J2xsIGJlIGNyZWF0aW5nIGVpdGhlciBhIHNpbXBsZSByZXBvcnQgb3Igc2xpZGUgZGVjayB1c2luZyBhbiBSIE1hcmtkb3duIGRvY3VtZW50IGp1c3QgbGlrZSB0aGlzIHRvIHNoYXJlIG91dCBzb21lIGtleSBmaW5kaW5ncyBmcm9tIG91ciBhbmFseXNpcy4gUmVnYXJkbGVzcyBvZiB3aGV0aGVyIHlvdSBwbGFuIHRvIHRhbGsgdXMgdGhyb3VnaCB5b3VyIGFuYWx5c2lzIGFuZCBmaW5kaW5ncyB3aXRoIGEgcHJlc2VudGF0aW9uIG9yIHdhbGsgdXMgdGhyb3VnaCB3aXRoIGEgYnJpZWYgd3JpdHRlbiByZXBvcnQsIHlvdXIgcHJlc2VudGF0aW9uIG9yIHJlcG9ydCBzaG91bGQgYWRkcmVzcyB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczoKCjEuICAqKlB1cnBvc2UqKi4gV2hhdCBxdWVzdGlvbiBvciBxdWVzdGlvbnMgYXJlIGd1aWRpbmcgeW91ciBhbmFseXNpcz8gV2hhdCBkaWQgeW91IGhvcGUgdG8gbGVhcm4gYnkgYW5zd2VyaW5nIHRoZXNlIHF1ZXN0aW9ucyBhbmQgd2h5IHNob3VsZCB5b3VyIGF1ZGllbmNlIGNhcmUgYWJvdXQgeW91ciBmaW5kaW5ncz8KCjIuICAqKk1ldGhvZHMqKi4gV2hhdCBkYXRhIGRpZCB5b3Ugc2VsZWN0ZWQgZm9yIGFuYWx5c2lzPyBXaGF0IHN0ZXBzIGRpZCB5b3UgdGFrZSB0b29rIHRvIHByZXBhcmUgeW91ciBkYXRhIGZvciBhbmFseXNpcyBhbmQgd2hhdCB0ZWNobmlxdWVzIHlvdSB1c2VkIHRvIGFuYWx5emUgeW91ciBkYXRhPyBUaGVzZSBzaG91bGQgYmUgZmFpcmx5IGV4cGxpY2l0IHdpdGggeW91ciBlbWJlZGRlZCBjb2RlLgoKMy4gICoqRmluZGluZ3MqKi4gV2hhdCBkaWQgeW91IHVsdGltYXRlbHkgZmluZD8gSG93IGRvIHlvdXIgImRhdGEgcHJvZHVjdHMiIGhlbHAgdG8gaWxsdXN0cmF0ZSB0aGVzZSBmaW5kaW5ncz8gV2hhdCBjb25jbHVzaW9ucyBjYW4geW91IGRyYXcgZnJvbSB5b3VyIGFuYWx5c2lzPwoKNC4gICoqRGlzY3Vzc2lvbioqLiBXaGF0IHdlcmUgc29tZSBvZiB0aGUgc3RyZW5ndGhzIGFuZCB3ZWFrbmVzc2VzIG9mIHlvdXIgYW5hbHlzaXM/IEhvdyBtaWdodCB5b3VyIGF1ZGllbmNlIHVzZSB0aGlzIGluZm9ybWF0aW9uPyBIb3cgbWlnaHQgeW91IHJldmlzaXQgb3IgaW1wcm92ZSB1cG9uIHRoaXMgYW5hbHlzaXMgaW4gdGhlIGZ1dHVyZT8KCiMjIyAqKkV4YW1wbGVzIGFuZCBUZW1wbGF0ZXMqKgoKWW91IGNhbiB2aWV3IGFuIGV4YW1wbGUgcHJlc2VudGF0aW9uIGZyb20gRUNJIDU4OCBoZXJlOsKgW1w8aHR0cHM6Ly9zYmtlbGxvZ2cuZ2l0aHViLmlvL2VjaS01ODgvdW5pdC0xL3VuaXQtMS1wcm9kdWN0Lmh0bWxcPl0oaHR0cHM6Ly9zYmtlbGxvZ2cuZ2l0aHViLmlvL2VjaS01ODgvdW5pdC0xL3VuaXQtMS1wcm9kdWN0Lmh0bWwpey51cml9CgpBbmQgdXNlIG15IFIgTWFya2Rvd24gcHJlc2VudGF0aW9uIGZpbGUgYXMgYSB0ZW1wbGF0ZSBpZiB5b3UgbGlrZTrCoFtcPGh0dHBzOi8vZ2l0aHViLmNvbS9zYmtlbGxvZ2cvZWNpLTU4OC9ibG9iL21haW4vdW5pdC0xL3VuaXQtMS1wcm9kdWN0LlJtZFw+XShodHRwczovL2dpdGh1Yi5jb20vc2JrZWxsb2dnL2VjaS01ODgvYmxvYi9tYWluL3VuaXQtMS91bml0LTEtcHJvZHVjdC5SbWQpey51cml9CgojIyMgKirwn5GJIFlvdXIgVHVybioqICoq4qS1KioKCk5vdyB0aGF0IHlvdSd2ZSBiZWNvbWUgbW9yZSBmYW1pbGlhciB3aXRoIHRoaXMgZGF0YXNldCBhbmQgdGhlIHNvY2lhbCBuZXR3b3JrIHBlcnNwZWN0aXZlLCB3aGF0IG90aGVyIGFzcGVjdHMgb2YgdGhpcyBkYXRhc2V0LCBvciBhIGRhdGFzZXQgeW91IGFyZSBpbnRlcmVzdGVkIGluIGV4cGxvcmluZywgY291bGQgeW91IGludmVzdGlnYXRlPwoKXC0KCldoYXQgc3BlY2lmaWMgcmVzZWFyY2ggcXVlc3Rpb25zIG1pZ2h0IHlvdSBhc2sgdGhhdCB3b3VsZCBiZSBoZWxwZnVsIGZvciBiZWluZyB1bmRlcnN0YW5kaW5nIGFuZCBpbXByb3ZpbmcgbGVhcm5pbmcsIG9yIHRoZSBjb250ZXh0IGluIHdoaWNoIHRoZSBkYXRhIGlzIGNvbGxlY3RlZD8KClwtCgojIyMg8J+ntiBLbml0ICYgQ2hlY2sg4pyFCgpDb25ncmF0cyEgWW91J3ZlIGZpbmlzaGVkIHRoZSBVbml0IDEgR3VpZGVkIFdhbGt0aHJvdWdoIGFuZCBhcmUgcmVhZHkgZm9yIHNvbWUgaW5kZXBlbmRlbnQgYW5hbHlzaXMgbmV4dCB3ZWVrIQoKVG8gY29tcGxldGUgdGhpcyBhc3NpZ25tZW50LCBrbml0IHlvdXIgZG9jdW1lbnQgYW5kIHNlbmQgbWUgYW4gZW1haWwgYXQgc2JrZWxsb2dcQG5jc3UuZWR1IGxldHRpbmcgbWUga25vdyB5b3UncmUgYWxsIHNldC4KCiMjIFJFRkVSRU5DRVMK